OptQuest 10.2 Optimization API
The OptQuest 10 API is one declarative interface with bindings for Java, C#, C++, C and Python. The same model definition and the same calls work in all five languages. A COM interface gives Automation clients (VBA, VBScript, VB6 and Excel) the C# calls. In Java, the OptQuest 9 API is still supported, and OptTek has no plan to deprecate it. In C#, C++, C and Python, the OptQuest 10 API is the only interface to the OptQuest Engine.
Overview
What Is Optimization?
Optimization finds the values of decision variables that give the best result for an objective while they satisfy the constraints. The OptQuest® Engine, developed by OptTek Systems, Inc., answers questions such as these:
- Resource allocation: How should a budget be split across uses to maximize return when product demand, machine reliability and raw-material supply are uncertain?
- Production scheduling: Which machine configuration is most efficient when demand and operating conditions change?
- Material flow: Where should raw materials be placed, and in which order released, to minimize waiting time?
- Workforce planning: How should staff be allocated to reduce lead time and labor cost?
- Portfolio optimization: How should an investment portfolio be allocated to maximize return?
For most problems, it is not practical to evaluate every combination of values. The OptQuest Engine chooses which combinations to evaluate next based on the results of all of the previously evaluated solutions. ### OptQuest Engine
Search Algorithm and Metaheuristics
The OptQuest Engine is a black-box global optimizer. It makes no assumption about the shape of the objective or the constraints. It needs no formula that gives the outputs from the inputs, and no derivatives, only the values that your evaluation returns. The engine uses metaheuristics: it records how earlier trial solutions performed, and it combines good trial solutions to make new ones. For a simulation that gives a different result each time it runs, the engine can evaluate each trial solution several times and combine the results (see § Concepts › Stochastic Simulation Optimization).
Algorithm Composition
The engine combines several known techniques along with proprietary custom approaches for various problem types:
- Linear and mixed-integer programming: when the objective and the constraints are linear, the engine can solve the problem exactly.
- Design of experiments: the engine spreads the first trial solutions over the ranges of the variables.
- Scatter search: the engine keeps a reference set of the best trial solutions and makes new trial solutions by combining members of the set.
- Local search: a Nelder-Mead search for continuous variables, and moves of one step for discrete variables.
- Enumeration: when the variables have few enough combinations, the engine evaluates all of them.
- A Kriging metamodel: with two or more variables, the engine fits an approximation to the trial solutions evaluated so far and uses it to propose new ones.
Concepts
This chapter introduces the parts of an OptQuest model and the loop the engine uses to evaluate solutions. Read it for orientation. The signature of every function mentioned here is in § API Documentation.
Model Components
In the OptQuest Engine, a model is a structured description of an optimization problem. It has one or more decision variables, one or more objectives and, optionally, one or more constraints. With a single objective, OptQuest refines a single best solution that maximizes or minimizes it. With several objectives, OptQuest builds a Pareto frontier: the set of solutions that represent the best trade-offs among the objectives. See § Overview › OptQuest Engine for a summary of the search algorithms.
Names
Every model component (variable, output, expression, objective, constraint, group and sample metric) has a name. These rules apply:
- Names are matched without regard to case.
Flowandfloware the same name, in the API and in expressions. So a model cannot have bothFlowandflow: the second Add call fails because the name already exists. The name lists (GetInputNamesandGetOutputNames) report each name as you wrote it when you added it. - A name must be unique across the whole model.
- A variable name must not be the name of a function or a constant of the expression language, such as
rate,max,piore(see § Reference › Functions and Constants Available In Expressions). In Java the Add call throwsCOptQuestExceptionwith the message “The variable name is a reserved function name.” In the other languages the Add call succeeds, and the model fails when it initializes, with the same message. - A name must not be empty, and it must not contain whitespace or semicolons.
- A variable name must not start with a digit. Objective, constraint, group and sample-metric names may.
- Use ASCII characters only. The native clients (C, C++, C#, COM and every binding built on them) exchange names with the engine as single-byte text, so a non-ASCII name is mangled.
- The element names supplied to a composite variable (permutation members, mixture components, sequence components, choices, DAG, tree and path nodes, topological sequence tasks, policy sequence items and features) follow the same rules and must not contain commas. Several model-definition statements separate their elements with a comma, so a comma inside an element name splits it.
The element names that the engine generates itself can contain commas (m@1,2). You read those back from the name lists. The members of a selection variable, an exchangeable group, a fix group and a float group are names of variables that are already in the model, so a member can be a generated element name with commas, such as m@1,2 or n@1,2,3.
Names in expressions. An expression in an expression variable, an objective, a constraint or a sample metric refers to a variable by a name that GetInputNames or GetOutputNames returns. For a container or special purpose variable, that is an element name, such as v@2, dir@theta or pol@i1, and never the base name (v, dir, pol). The base name has no value of its own. A model with an expression that names a base name, such as pol <= 7, fails when it initializes, and the error gives the reason “The name is the base name of a container or manifold variable. Use its element names, such as name@1.” and the base name. The engine messages call a special purpose variable a manifold variable. The Notes of each type list its element names. Write an element name that contains a comma in brackets, for example [m@1,2].
Decision Variables
Decision variables are the parameters the optimizer is allowed to vary. The API groups them in these families. Each family is documented in § API Documentation › Decision Variables:
- Standard: continuous, integer, discrete, binary, design (deprecated), enumeration, tuple and geolocation.
- Container: vectors, matrices and arbitrary-dimensional (
ND) arrays of continuous, integer, discrete or binary elements. - Permutation (deprecated): an ordering of named elements. The engine creates one integer position variable per element. Use a sequence variable instead.
- Special purpose: variables whose values must stay inside a structured set, such as an angle on an arc, a ranking of items or a matrix of limited rank. In every solution that the engine generates, the values are inside the set. The combinatorial family has mixtures (simplex), sequences, multi-stage sequences, policy sequences, choices, multi-choices, assignments, item and budgeted selections, partitions, DAGs, trees, paths and topological sequences. The geometric family has angles, spherical angles, regions and spherical regions. The smooth family has low-rank matrices, time-series vectors, and B-spline, Catmull-Rom spline and Fourier representations of vectors and matrices, each with or without a baseline correction.
- Random: random draws from a named probability distribution (Beta, Cauchy, Chi-Square, Exponential, Gamma, Log-Normal, Normal, Pareto, Poisson, Power, Spherical Elevation, Student’s t, Uniform and Weibull). The engine draws a new value at the start of every replication.
Restrictions and groupings that apply to variables after they exist (exclusive ranges, selection gates, exchangeable groups and fix/float groups) are documented in § API Documentation › Variable Modifiers.
Output Variables
Output variables hold results that the simulation (or an external computation) must supply for each trial solution. OptQuest does not assign values to them. Use an output variable whenever an objective or constraint depends on a quantity that cannot be written as a closed-form expression of the input variables. If the evaluator does not call SetValue for an output before it submits the solution, the output stays NaN. For the effect on the objectives and constraints, see § API Documentation › Output Variables. The API supports scalar outputs, output vectors, output matrices and arbitrary-dimensional output ND variables.
Expression Variables
Expression variables are derived values. The optimizer does not choose them and the simulation does not set them. Each expression variable has a string expression, in the same language as objectives and constraints, that the engine recomputes after every solution evaluation. An expression variable can reference input, output and other expression variables. Objectives, constraints, sample metrics and further expression variables can reference it in turn.
Objectives
An objective is an expression over decision variables and output variables that measures a goal. Each objective has a direction:
- Maximize: the engine seeks the highest value of the expression (for example, profit).
- Minimize: the engine seeks the lowest value (for example, cost).
For example, an objective can be maximize 2*VariableA + 3*VariableB, where VariableA and VariableB are input or output variables. With several objectives, OptQuest finds the set of non-dominated solutions: the frontier of the trade-offs among the objectives.
For stochastic models (with replications), SetObjectiveStatistic selects which statistic of the per-replication objective values (mean, median, percentile, standard deviation, variance, coefficient of variation, min, max or sum) is the value that the optimizer compares, and SetObjectiveConfidence lets the engine stop replicating early once a configured confidence interval is reached. See § API Documentation › Objectives.
Constraints
A constraint is an expression that limits the feasible region. It can reference variables, objectives or both. OptQuest supports:
- Linear constraints, such as
a*VariableA + b*VariableB <= c, where the coefficients and the bound are constants. - Non-linear constraints, such as
pow(VariableA, 2) + VariableB <= 100. See § Reference › Functions and Constants Available In Expressions for the operators and functions.
The engine enforces a constraint at one of two times, depending on what the constraint references:
- A constraint that references only input (decision) variables is enforced before the evaluator runs. The engine makes sure that the evaluator receives only input values that satisfy these constraints, so the simulator never has to handle or reject an infeasible input combination. If no input values can satisfy these constraints, the run ends with the termination reason Infeasible (12).
- A constraint that references an output variable (directly, or through an expression variable that depends on an output) cannot be checked until the simulation has run. The evaluator always runs. If the outputs violate the constraint, the engine records the solution and marks it infeasible. The engine still learns from these solutions and steers the search away from the infeasible region.
A constraint over the variable names of a special purpose variable, or over a random variable, is also checked after evaluation. The element names of a container variable, and the names of an item selection or a budgeted selection variable, are ordinary inputs, so a constraint over them is enforced before evaluation. See § API Documentation › Decision Variables › Special Purpose Variables: Common Behavior.
The engine has no strict inequality: it reads < as <= and > as >=. It also accepts a violation of a constant bound up to a small tolerance, 1e-5 for each variable in a linear constraint over inputs. See § API Documentation › Constraints › Add Constraint.
The Optimization Loop
OptQuest is built for black-box simulation optimization, where the objective depends on the outputs of a simulation. The objective can be non-convex, discontinuous or non-differentiable. The engine runs this loop:
- Generate: build a trial solution by assigning a value to every input variable within its domain, subject to the constraints.
- Evaluate: compute the output values from the trial solution’s inputs, with a simulation, a complex function or an analytical expression.
- Learn: assess the evaluated solution to learn about the objective and the solution space.
- Refine: use what has been learned to generate the next trial solution.
The four workflows that run this loop (managed, concurrent, asynchronous managed and manual) are documented in § Optimization Workflows.
Model Immutability
An OptQuestModel has two stages: definition and execution. During definition, the client adds decision variables, output variables, expression variables, objectives, constraints and sample metrics, and configures their statistic and confidence parameters. Execution begins the first time the engine builds its internal representation of the model, which is the first call to any of these methods:
Optimize(...)orSample(...), in every overload (managed, concurrent or asynchronous).CreateSolution(),GetEmptySolution()orCopySolution(src), used by manual workflows.AddAllSolutions(srcModel), used to import evaluated solutions from another model.- The solution methods
Submit(),Reject(),Predict(),Evaluate(),Update(),AddSuggested(),AddEvaluated()andAddRequired(), which all need an initialized model.
You can also start execution explicitly with Initialize(). This is useful to find out whether the model is well formed before any solution is generated.
The first of these calls builds the engine’s internal data structures from the declared components and makes the model immutable. From then on, every configuration method is rejected, including the ones that do not add components. That includes adding decision, output and expression variables, objectives, constraints and sample metrics; the statistic settings (SetObjectiveStatistic, SetOutputStatistic); and the run-control settings SetReplications, SetSerialReplications, SetStopCycles, SetStopImprovement, SetStopTime, StopOnSuccessfulMILP, SuggestedSolutionsOnly, SetParallelHint, SetRandomSeed, SetSampleMethod, SetSampleVariogram and the SetSampleRDS* family. Such a call fails in the language’s standard way (see § Concepts › Error Handling).
These operations stay valid after initialization:
- Calling
Optimize(...)orSample(...)again. Successive runs accumulate solutions in the same model. - Reading solutions and metadata:
GetBestSolutions,GetAllSolutions,GetNumberOfCompletedIterations,GetMaxReplications,GetTerminationReason,DescribeandGetLastError. - Controlling a running asynchronous optimization with
Interrupt()andContinue()on the model. In Java, C#, C++ and C, the channel object has its ownInterrupt(), and aContinue()that reports whether the interrupt signal was raised rather than resuming the run. See § API Documentation › Running Managed Optimization and Sampling › Channel Continue, Interrupt and Get Number Of Parallel. - Importing solutions from another model with
AddAllSolutions(otherModel), which combines the results of independent runs without re-evaluation.
Immutability is a one-way transition. No call returns an initialized model to the definition stage. To change the structure of a model after a run, create a new OptQuestModel, define it again, and use AddAllSolutions to import the old solutions into it if you want them.
Stochastic Simulation Optimization
OptQuest supports stochastic simulations, where identical inputs can produce different outputs. Each trial solution (one combination of decision-variable values) is evaluated N independent times, called N replications, and the engine aggregates the per-replication results into one score that it uses to guide the search. The evaluator and the monitor are both called once per replication. For a trial with twenty replications, both callbacks run twenty times before the engine moves to the next trial. Across those twenty calls the decision-variable values are identical. Only random variables (declared with Add*RandomVariable) and any randomness inside the simulator itself change between replications.
There are two ways to configure the number of replications:
- Fixed replications: the engine runs the same number of replications for every trial solution. Configure it with
SetReplications(reps). C has no single-argument form; pass the same value forminandmax. - Variable replications with convergence monitoring: the engine runs at least
minreplications, then stops when the objective meets its confidence interval or when it reachesmax. Configure it withSetReplications(min, max)andSetObjectiveConfidence. WithoutSetObjectiveConfidence, the engine runsmaxreplications for every trial solution.SetObjectiveStatisticandSetOutputStatisticset how the engine combines the replications into one value. They do not stop the replications early.
min must be at least 1 and max at least min. A max of 1 runs without replications. A confidence interval needs two observations, so a min of 1 with a larger max runs at least two replications per trial.
See § API Documentation › Optimization Configuration and § API Documentation › Objectives for the signatures.
Error Handling
Each language reports errors in its own way:
- Java: throws
COptQuestException. The exception message and call stack contain the full error description. - C#, C++, Python: the failing function returns
false. CallGetLastError()on the model (get_last_error()in Python) for the same description that Java would place in its exception. Python adds one case of its own: an argument the binding itself refuses before the call, such as a ragged list of rows, a mixture bounds list of the wrong length or a path of fewer than two nodes, raisesValueErrorwith the method name. A refusal by the client or by the engine still returnsFalse. - C: the failing function returns
0. A non-zero return means success. CallOQGetLastError(model)for the description.
For the solution-level operations (Submit, Reject, Predict, Evaluate, Update, AddSuggested, AddEvaluated, AddRequired), read the error from the solution rather than the model: Java throws the same exception type; C#, C++ and Python call GetLastError() / get_last_error() on the OptQuestSolution; C calls OQGetLastSolutionError(sol). See § API Documentation › Utility Functions for the signatures.
GetLastError() / OQGetLastError() is sticky: a successful call does not clear it, so the text can be left over from an earlier, unrelated failure. Use the return code to decide whether a call failed, and read the error text only after a return code that is a failure value.
The description that GetLastError() / OQGetLastError() returns is a pointer into a per-thread buffer. It stays valid until the next GetLastError() call on the same thread. Another thread that records an error (a worker under a parallel Optimize, for instance) cannot invalidate a pointer this thread holds. Copy the string if it must outlive the next call.
No exception and no fault crosses the C boundary. When an OQ* function gets a NULL handle or a NULL array or string argument, or when an exception is raised inside the library, the function returns the call’s own failure value: 0 for the bool-valued calls, -1 for the int-valued counts and reasons, NaN for a value, "" for a borrowed string, and NULL for a handle or an allocated reply. Where a handle is available, the reason is recorded against it. A model is still usable after a call is refused this way. Array arguments must not be NULL unless their count is zero.
SubmitandRejectdo not follow the return convention above. In Java, C#, C++ and C they return the engine’s running count of completed iterations on success and exactly-1on failure. The count is0for a successful call while no iteration has completed yet (the first replication of a trial under replications, for example), so0is a success. Test these two functions with>= 0(or!= -1), never with!= 0or> 0.Predict,Evaluate,Update,AddSuggested,AddEvaluatedandAddRequiredfollow the ordinary convention. Python’ssubmit()andreject()apply the>= 0test internally and returnFalseonly on failure.
Common Errors
These are the errors and the silent results that new users see most often. The quoted text is what GetLastError() returns in C#, C++, C and Python. In Java, an engine error throws COptQuestException with the same description, and a call that the client refuses returns false with no message. A message from the engine contains the description shown, followed by a call stack.
| Message or symptom | Cause | What to do |
|---|---|---|
ERROR the model has no objective |
The model has no objective. In Java, Initialize and Optimize return false. |
Add an objective. The model stays in the definition stage, so you can add the objective and run again. |
ERROR duplicate name |
An Add call used a name that the model already has. Names are compared without regard to case. In Java, the call returns false. |
Use a different name. |
The variable name is a reserved function name. |
A variable has the name of a function or a constant of the expression language, such as rate or pi. |
Rename the variable. In C#, C++, C and Python, the engine reports the message when the model initializes, and the model cannot be changed after that. Build a new model. |
ERROR already initialized |
An Add or Set call came after the model was initialized. In Java, the call returns false. |
Make every Add and Set call before the first run. To change a model after a run, build a new model (see § Model Immutability). |
The variable was not found. Error Token = <name> |
An objective, a constraint or an expression variable uses a name that the model does not declare. The engine reports the message when the model initializes. | Check the spelling. A container or special purpose variable has generated names, such as v@1; see § Get Variable Names. Build a new model to correct the error. |
ERROR BAD VALUE NAME: <name> |
SetValue used a name that the model does not declare. The engine reports the message when the solution is sent, for example by Submit. In Java, SetValue returns false. |
Check the spelling of the output name. |
ERROR BAD SOLUTION ID |
Submit or Reject was called on a solution that the engine did not issue, such as a solution from GetEmptySolution or CopySolution. Java does not refuse this call. |
Give such a solution to the engine with AddSuggested, AddEvaluated or AddRequired. |
ERROR invalid solution |
A call was made on a solution whose IsValid() is false. In Java, SetValue returns false and Submit returns -1. |
Test IsValid() after each CreateSolution(). When it is false, read GetTerminationReason(). |
Constraints are infeasible. |
No input values satisfy the constraints that use only input variables. The termination reason is Infeasible (12), and CreateSolution returns an invalid solution. |
Check the constraints and the bounds of the variables that they use. |
Bad value for the replication confidence error percent. |
The epct argument of SetObjectiveConfidence is not greater than 0 and less than 1. The engine reports the message when the model initializes. |
Pass a fraction: 0.05 for 5 percent. |
| The run stops after 50 iterations, and the termination reason is 14. There is no message. | No license is set. | Call SetLicense with your license key. |
Optimize returns false, and GetLastError() is empty. |
The run ended early without an error, for example because the monitor returned false. |
Read GetTerminationReason() (§ Get Termination Reason). |
The best solution is infeasible, and its objective is NaN. There is no message. |
The evaluator rejected every trial solution. In Python, an evaluator without a return statement returns None, and the engine rejects the trial solution. |
End a Python evaluator with return True. |
| An output reads NaN, and an objective or a constraint that uses it is NaN. | The evaluator did not call SetValue for that output. |
Set every output before you submit the solution, or reject the solution. |
Your First Optimization
This section gives a complete program and its output. The program finds the values of x and y that give the smallest cost. The engine asks for one set of values of x and y at a time. That set of values is a trial solution. For each trial solution, the engine calls the evaluator, which stands in for your simulation. The evaluator reads the inputs, computes the output and writes the output back. One iteration is one trial solution with all its replications (see § Stochastic Simulation Optimization). This model has no replications, so each iteration is one call of the evaluator.
In Java, GetValue and SetValue declare throws COptQuestException, so the evaluator catches that exception.
import com.opttek.optquest.COptQuestException;
import com.opttek.optquest.IOptQuestEvaluator;
import com.opttek.optquest.OptQuestModel;
import com.opttek.optquest.OptQuestSolution;
import java.util.List;
public class FirstOptimization {
public static void main(String[] args) throws COptQuestException {
OptQuestModel model = new OptQuestModel();
// model.SetLicense("your-license-key"); // without a license, a run stops after 50 iterations
model.AddContinuousVariable("x", -10, 10); // decision variables and their bounds
model.AddContinuousVariable("y", -10, 10);
model.AddOutputVariable("cost"); // a result that the evaluator writes
model.AddMinimizeObjective("obj", "cost"); // what "best" means
IOptQuestEvaluator evaluator = sol -> {
try {
double x = sol.GetValue("x");
double y = sol.GetValue("y");
double cost = (x - 3.0) * (x - 3.0) + (y + 1.0) * (y + 1.0); // replace with your simulation
sol.SetValue("cost", cost);
return true; // true: use this result
} catch (COptQuestException e) {
return false; // false: reject this trial solution
}
};
model.Optimize(40, evaluator); // run 40 iterations
List<OptQuestSolution> best = model.GetBestSolutions();
if (!best.isEmpty()) {
OptQuestSolution b = best.get(0);
System.out.println("x = " + b.GetValue("x") + ", y = " + b.GetValue("y")
+ ", cost = " + b.GetValue("obj") + ", feasible = " + b.IsFeasible());
}
System.out.println("iterations = " + model.GetNumberOfCompletedIterations()
+ ", termination reason = " + model.GetTerminationReason());
}
}The same program in Python:
import optquest
def evaluate(sol):
x = sol.get_value("x")
y = sol.get_value("y")
cost = (x - 3.0) ** 2 + (y + 1.0) ** 2 # replace with your simulation
sol.set_value("cost", cost)
return True # True: use this result
model = optquest.OptQuestModel()
# model.set_license("your-license-key") # without a license, a run stops after 50 iterations
model.add_continuous_variable("x", -10, 10) # decision variables and their bounds
model.add_continuous_variable("y", -10, 10)
model.add_output_variable("cost") # a result that evaluate() writes
model.add_minimize_objective("obj", "cost") # what "best" means
model.optimize(40, evaluate) # run 40 iterations
best = model.get_best_solutions()
if best:
b = best[0]
print(f"x = {b.get_value('x')}, y = {b.get_value('y')}, "
f"cost = {b.get_value('obj')}, feasible = {b.is_feasible()}")
print(f"iterations = {model.get_number_of_completed_iterations()}, "
f"termination reason = {model.get_termination_reason()}")The Java program prints:
x = 2.9083081205692034, y = -0.7155144834659386, cost = 0.08933940987120347, feasible = true
iterations = 40, termination reason = 6
The Python program prints the same values, with True in place of true. The engine uses the same random seed each time, so each run of the program gives the same result (see § Set Random Seed).
The minimum is at x = 3 and y = -1, where the cost is 0. Termination reason 6 is Max Iterations: the run completed the 40 iterations that the program asked for. More iterations give a result closer to the minimum. With a license set, the same program gave these best costs:
| Iterations | Best cost |
|---|---|
| 20 | 4.34 |
| 40 | 0.0893 |
| 100 | 4.7e-6 |
| 200 | 4.7e-7 |
| 500 | 1.5e-8 |
Without a license, the model runs in demo mode, and a run stops after 50 iterations (see § Set License).
To adapt the program to your problem:
- Add one decision variable for each quantity that you control. For a comparison of the variable types, see § Choosing a Variable Type.
- Add one output variable for each result of your simulation that an objective or a constraint uses.
- Add the objective, and add the constraints if you have them.
- In the evaluator, call your simulation and write every output variable with
SetValue. If the simulation fails, returnfalseto reject the trial solution. - Set the number of iterations, run the optimization, and read the best solution.
The full order of the calls is at the start of § API Documentation. The other ways to run the loop are in § Optimization Workflows.
Optimization Workflows
OptQuest offers four workflows for driving the optimization loop: a managed workflow, in which the engine owns the loop; a concurrent variant, in which the engine spreads evaluation across threads; an asynchronous variant, in which the host application stays responsive during a long run; and a manual workflow, in which the client performs every step itself.
The code examples below are in Java. The OptQuest 10 API is the same in all five languages: C#, C++, C and Python use their own syntax with otherwise identical signatures. The COM interface has the C# calls, with the differences listed in § Reference › Linking OptQuest To Your Project › COM. The signature of every workflow is in § API Documentation › Running Managed Optimization and Sampling and § API Documentation › Manual Optimization.
Managed Optimization
In managed optimization the engine runs the optimization loop.
Simple Optimization
When the objectives and constraints are direct functions of the input variables (no external simulation), OptQuest runs the loop with no evaluation callback. The client specifies only the number of iterations.
OptQuestModel model = new OptQuestModel();
// Define input variables, objectives, and constraints
// ...
// Perform 100 iterations of the optimization loop
model.Optimize(100);Simulation-Based Optimization
When the outputs come from a simulation, the client supplies a callback that evaluates each solution. OptQuest calls it once for each replication of each trial solution.
OptQuestModel model = new OptQuestModel();
// Define input variables, objectives, and constraints
// ...
// Perform 100 iterations, invoking customEvaluation for each solution
model.Optimize(100, customEvaluation);Concurrent Optimization
For expensive evaluations, OptQuest evaluates several solutions in parallel. The client specifies the number of threads. OptQuest creates the solutions, dispatches them across the threads and synchronizes the generate and learn steps.
OptQuestModel model = new OptQuestModel();
// Define input variables, objectives, and constraints
// ...
// Perform 100 iterations with 5 concurrent threads, invoking customEvaluation
model.Optimize(5, 100, customEvaluation);Asynchronous Managed Optimization
For a long run, the client starts the optimization on a background thread and keeps the main thread responsive. The main thread can interrupt the run through a channel.
OptQuestModel model = new OptQuestModel();
// Define input variables, objectives, and constraints
// ...
// Create a channel for 5 concurrent optimizations
OptQuestModelChannel channel = model.CreateAsyncChannel(5);
// Start asynchronous optimization in a background thread
Thread background = new Thread(() -> {
try {
// Blocks until 100 solutions are evaluated or interrupted
model.Optimize(channel, 100, customEvaluation);
} catch (COptQuestException e) {
e.printStackTrace();
}
});
background.start();
// Interrupt optimization in response to a user event
channel.Interrupt();
// Wait for the optimization to terminate gracefully
background.join();Python has no channel object. Start model.optimize(...) on a background thread, pass npar to it directly, and call model.interrupt() on the model from the main thread. model.continue_opt() clears the interrupt so that a later optimize() can run.
Manual Optimization
For fine-grained control, the client performs each step of the loop itself. Use it for HPC, distributed and other custom concurrent setups, in which the client requests each next solution, then manages evaluation and submission.
OptQuestModel model = new OptQuestModel();
model.AddContinuousVariable("x", 0, 10);
model.AddOutputVariable("y");
model.AddMinimizeObjective("obj", "y");
for (int i = 0; i < 100; i++) {
// Ask the engine for the next trial solution
OptQuestSolution solution = model.CreateSolution();
if (!solution.IsValid()) {
break; // the run has ended; read GetTerminationReason() for the reason
}
// Read the inputs, compute the outputs and write them back by name
double x = solution.GetValue("x");
double y = runSimulation(x); // your code
solution.SetValue("y", y);
// Give the result to the engine: -1 is a failure, 0 or more is a success
if (solution.Submit() < 0) {
break;
}
}
List<OptQuestSolution> best = model.GetBestSolutions();
if (!best.isEmpty()) {
System.out.println("x = " + best.get(0).GetValue("x") + ", y = " + best.get(0).GetValue("y"));
}With runSimulation(x) equal to (x - 2) * (x - 2) and no license, the program prints x = 2.000606391779585, y = 3.6771099034838766E-7. In demo mode, the 51st CreateSolution returns an invalid solution with the termination reason Max Demo Iterations (14), so the loop ends after 50 passes.
Without replications, each pass of the loop evaluates one trial solution. With replications, each pass evaluates one replication. In Java, CreateSolution and Submit throw COptQuestException when the engine reports an error. In C#, C++ and Python, call GetLastError() on the solution after Submit reports a failure.
Adaptive Sampling
Adaptive Sampling, introduced in OptQuest 10, is an alternative to optimization for exploring a design space. Optimization seeks one best point, a minimum or a maximum. Adaptive Sampling builds an accurate picture of the response surface across the whole domain with as few evaluations as possible. Use it when the goal is to understand the behavior of the domain: trends, boundaries and regions of interest, rather than a single optimum.
The sampling engine works like the optimization engine. It generates trial solutions, evaluates them and uses the results to guide the next choice. The difference is the goal. Adaptive Sampling monitors a user-defined metric, which has a value and an uncertainty (error). The engine builds an internal model of the metric across the domain, predicts the response in unexplored areas and selects the next solution where it expects to learn the most. The engine refines the model with each evaluated solution.
Sampling Loop
The Adaptive Sampling loop has five steps:
- Generate: build a trial solution by assigning a value to every input variable within its domain.
- Evaluate: compute the output values from the trial solution’s inputs, with a simulation, a complex function or an analytical expression.
- Model: update the internal model of the response surface from all evaluated solutions.
- Select: find the most informative region of the domain under the current model.
- Refine: generate the next trial solution in that region.
Sampling Strategies
Each strategy defines what “informative” means. Select one by passing its flag to SetSampleMethod (see § API Documentation › Adaptive Sampling Configuration). The constants below are the C names. The constants for the other languages are listed with SetSampleMethod.
- Uniform Sampling (
OQSampleMethodUniform): the simplest and fastest strategy. The engine generates solutions that cover the domain evenly and increases the sample density until the run ends. It does not look at the metric, so it suits an initial exploration of the domain. - Variance-Based Sampling (
OQSampleMethodVariance): for stochastic simulations. The engine uses both the response and its error, accounts for the correlation between solutions, and samples next where the uncertainty is highest (the least-known area). This reduces the global uncertainty of the response fastest. - Boundary-Finding Sampling (
OQSampleMethodZero): the engine samples where the metric is predicted to cross zero. To find a different contour, subtract the wanted value from the metric expression. For example, to map radio signal strength in a city, use a metric ofsignal - 0.5. The engine then samples densely along the contour wheresignal = 0.5, which maps the transition boundary. - Gradient-Based Sampling (
OQSampleMethodGradient): the engine samples where the response changes fastest (the largest gradient). Use it to find the dynamic parts of the domain. - Minimum Response Sampling (
OQSampleMethodMin): like optimization, but with a sampling goal. The engine samples densely where the response is small, so the low-response region is characterized in detail without a search for the exact minimum. - Maximum Response Sampling (
OQSampleMethodMax): the opposite of minimum response sampling. The engine samples densely where the response is large. - Response Distribution Sampling (
OQSampleMethodRDS): the engine tracks the probability density of the responses and compares it to a wanted distribution. The engine puts new samples where it predicts that they bring the measured density closer to the wanted one. A common use is to produce balanced training data for a machine-learning model. See § Reference › Probability Distributions for the algorithm and the supported distributions.
The flags above can be combined with the OQSampleMethodStochastic, OQSampleMethodDynamic and OQSampleMethodAsync modifiers. See § Set Sampling Method for the full combination table.
Applications
Adaptive Sampling suits applications that need a picture of the whole domain, such as:
- Characterizing trade-offs in multi-variable systems.
- Mapping boundaries or transition zones.
- Exploring stochastic or noisy simulations to quantify uncertainty.
- Finding regions of rapid change or extreme response for further analysis.
- Creating training data with a wanted probability distribution.
API Documentation
This chapter documents every function of the OptQuest 10 API, with its signature in Java, C#, C++, C and Python. A COM interface for Automation clients (VBA, VBScript, VB6, Excel) is the COM form of the C# interface; see § Reference › Linking OptQuest To Your Project › COM for its naming and marshalling differences. Unless an entry says otherwise, the Java, C# and C++ implementations behave identically. In C the caller frees some resources by hand, and each entry that needs it says so. Any language that can call C functions can use the C interface.
To define a model, call the functions in this order:
- Create the model: create an
OptQuestModel. It holds every model component. - Add input variables: add one or more decision variables. They define the search space.
- Add output variables (optional): add an output variable for each result of the simulation that an objective or constraint needs and that cannot be written as an expression of the inputs.
- Define objectives: add one or more objectives, each an expression over input and output variables with a maximize or minimize direction.
- Define constraints (optional): add constraints as expressions over the variables to limit the feasible region.
- Configure the run: set replications, stopping criteria, the sampling method and the other run settings as needed.
- Run: call one of the managed
OptimizeorSamplemethods, or drive the loop by hand, then read the solutions back.
Conventions
The rules below apply to every entry in this chapter. The entries do not repeat them.
Return Values and Errors
A function that has no other result reports success or failure this way:
- Java returns
trueon success andfalsewhen it refuses the call (for example, a duplicate name or an unknown variable). A method whose signature declaresthrows COptQuestExceptionthrows that exception when the engine reports an error. A method without the clause never throws. - C#, C++ and Python return
trueon success andfalseon failure. CallGetLastError()on the model for the description. For the solution methods (Submit,Reject,Predict,Evaluate,Update,AddSuggested,AddEvaluated,AddRequiredandSetValue), callGetLastError()on the solution instead. - C returns a non-zero value on success and
0on failure. CallOQGetLastError(model)after a model function andOQGetLastSolutionError(sol)after a solution function.
Submit and Reject return an iteration count instead of a flag; see their entries. The sticky error text, the per-thread error buffer and the rule that no exception crosses the C boundary are described in § Concepts › Error Handling. An entry has its own Returns section only when its function does not follow this rule.
Names
Every name argument follows the rules in § Concepts › Names: unique across the model, not empty, no whitespace, no semicolons, ASCII only, and not starting with a digit for a variable. The element names supplied to a composite variable must not contain commas either. The members of a selection variable and of a group can be generated element names with commas, such as m@1,2. A function that receives a name that breaks these rules fails.
A variable name must also not be the name of a function or a constant of the expression language. In Java, the Add call fails. In the other languages, the Add call succeeds, and the model fails when it initializes.
Numbering
The index and position numbers that OptQuest reports start at 1. These are:
- the selected tuple of a Tuple Variable and the selected location of a Geolocation Variable;
- the option of a Design or Choice Variable;
- the bin of an Assignment Variable and the group of a Partition Variable;
- the rank of a Sequence, Multi-Stage Sequence or Topological Sequence Variable, and the position of an element of a Permutation Variable;
- the position of a node on a Path Variable;
- the element numbers in generated names, such as
v@1for the first element of a vector; - the iteration number (
GetIteration) and the replication number (GetReplication).
Java, C#, C, C++ and Python number their arrays from 0. To use a reported value k as an index into your own array, read element k - 1. A value of 0 has its own meaning: an Assignment bin of 0 means that the item is in no bin, and a Path position of 0 means that the node is not on the path.
These numbers start at 0: the index i of GetBestSolutionsAt(i), GetAllSolutionsAt(i), GetInputNameAt(i) and GetOutputNameAt(i) in C and C++, and the counter on the --- line of a GETBESTSOLUTIONS or GETALLSOLUTIONS reply in the Standard I/O Interface.
Strings and Arrays in C and C++
Every string argument is a null-terminated const char*. An array of strings is a const char** with its element count passed alongside. The entries state only the layout of arrays that is not obvious from the signature.
Model Lifecycle
Create Model
| Language | Function Signature |
|---|---|
| Java | new OptQuestModel() |
| C# | new OptQuestModel() |
| C++ | OptQuestModel() |
| C | HOptQuestModel OQCreateModel() |
| Python | OptQuestModel() |
Description
Creates a new OptQuestModel. The model holds every component you add to it. Create the model before you add variables, objectives or constraints.
Notes
- In Java, C#, C++ and Python the constructor allocates the resources.
- In C,
OQCreateModel()returns anHOptQuestModelhandle. Free it withOQDeleteModel()when you are done with the model.
Delete Model
| Language | Function Signature |
|---|---|
| Java | Garbage Collected |
| C# | Garbage Collected |
| C++ | Destructed |
| C | void OQDeleteModel(HOptQuestModel model) |
| Python | Garbage Collected |
Description
Releases the resources of an OptQuestModel. Java, C# and Python reclaim the object through garbage collection. In C++ the destructor runs when the object goes out of scope. In C, call OQDeleteModel on the handle.
Notes
- In C++, scope the
OptQuestModelobject so that its destructor runs when you are done with it.
Set License
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetLicense(String license) |
| C# | bool OptQuestModel.SetLicense(string licenseid) |
| C++ | bool OptQuestModel::SetLicense(const char* licenseid) |
| C | int OQSetLicense(HOptQuestModel model, const char* licenseid) |
| Python | bool OptQuestModel.set_license(str license_id) |
Description
Sets the license key that an OptTek representative supplied. If SetLicense is never called, or is called with an empty string, the model runs in demo mode: every optimization stops after 50 iterations regardless of the requested iteration count. CreateSolution then returns an invalid solution, and GetTerminationReason reports Max Demo Iterations (14). A managed Optimize returns false with no error text.
Log Setup
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.LogSetup(String filespec) |
| C# | bool OptQuestModel.LogSetup(string filespec) |
| C++ | bool OptQuestModel::LogSetup(const char* filespec) |
| C | int OQLogSetup(HOptQuestModel model, const char* filespec) |
| Python | bool OptQuestModel.log_setup(str file_spec) |
Description
Writes an XML description of the model’s configuration to the file at filespec. Use it for debugging, or to share a model with OptTek support.
Notes
filespecmust be a valid, writable file path. It may contain spaces.- The setup log is well formed only after its closing elements are written. The engine writes them when you delete the model, so a log read after the model is gone is complete. A Java caller that holds the
OptQuestModelobject directly can write them without deleting the model by callingCleanUp(), which also releases the solution log. CallingCleanUp()more than once is harmless.
Log Solutions
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.LogSolutions(String filespec) |
| C# | bool OptQuestModel.LogSolutions(string filespec) |
| C++ | bool OptQuestModel::LogSolutions(const char* filespec) |
| C | int OQLogSolutions(HOptQuestModel model, const char* filespec) |
| Python | bool OptQuestModel.log_solutions(str file_spec) |
Description
Writes every solution evaluated during optimization or sampling to the file at filespec. Use it to share solution data with OptTek support for troubleshooting or analysis.
Notes
filespecmust be a valid, writable file path. It may contain spaces.
Initialize Model
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.Initialize() throws COptQuestException |
| C# | bool OptQuestModel.Initialize() |
| C++ | bool OptQuestModel::Initialize() |
| C | int OQInitialize(HOptQuestModel model) |
| Python | bool OptQuestModel.initialize() |
Description
Builds the engine’s internal representation of the model and moves the model from the definition stage to the execution stage. After this call the model is immutable (see § Concepts › Model Immutability).
The call is optional: every method that needs an initialized model calls it first. Call it explicitly to find out whether the model is well formed before any solution is generated. Without the explicit call, you see the error later as a generic failure of the first CreateSolution() or Optimize(). With it, you can inspect the error at a known point.
Notes
- Initializing an already-initialized model is harmless. The call returns the result of the first initialization.
- A model that is refused before the engine is asked stays in the definition stage, so the
Add*andSet*methods keep working and you can correct the model and initialize it again. The most common case is a model with no objective, reported asERROR the model has no objective. - A model that the engine itself refuses moves to the execution stage all the same, because the engine has already received it.
AddContinuousVariable("o", "nonexistent")followed byInitialize()returnsERROR ... The variable was not found, and every laterAdd*/Set*call and every laterInitialize()returnsERROR already initialized. Build a new model to correct that class of error.
Describe Model
| Language | Function Signature |
|---|---|
| Java | String OptQuestModel.Describe() |
| C# | string OptQuestModel.Describe() |
| C++ | const char* OptQuestModel::Describe() |
| C | const char* OQDescribe(HOptQuestModel model) |
| Python | str OptQuestModel.describe() |
Description
Returns the model as the block of definition commands that the binding sends to the engine. This is the text documented in § Reference › Standard I/O Interface › Model Definition Commands. Use it as a debugging aid: the text is what the binding built from your API calls, including the numeric formatting used on the wire, and you can capture it and replay it through the STDIO interface.
Returns
- The model definition block, one command per line.
Notes
- In C and C++, the model owns the returned pointer. The next call to
Describeinvalidates it.
Decision Variables
A decision variable is a value the optimizer chooses. Every function in this group adds one variable, or one family of generated variables under a base name, to the model. The families are:
- Standard: regular variables with one value each.
- Container: many independent standard variables under one base name.
- Permutation (deprecated): an ordering of named elements, one position variable per element. Use a sequence variable instead.
- Special purpose: a value inside a structured set. In every solution that the engine generates, the value is inside the set.
- Random: a random draw at the start of every replication.
Read the names of the variables in a model, including the generated element names, with GetInputNames (§ Working With Solutions › Get Variable Names).
Choosing a Variable Type
Find your decision in the first column. The full rules of each type are in its entry below.
| Your decision | Type | Example |
|---|---|---|
| A number in a range | Continuous | a flow rate from 0 to 50 L/s |
| A whole number in a range | Integer | the number of pumps, from 1 to 4 |
| A number in fixed steps | Discrete | a pipe size in steps of 0.5 inch |
| Yes or no | Binary | whether to add a storage tank |
| One number from a list of numbers | Enumeration | a standard resistor value |
| One option from a list of options that have no order | Choice | a supplier or a machine type |
| One row of a table of numbers, where rows with close values give similar results | Tuple | a catalog pump, given by its flow and its head |
| One site from a list of map points | Geolocation | one of 12 candidate depots |
| Many similar numbers that share their bounds | Vector, Matrix or ND container | a weight for each of 20 sensors |
| Proportions that add up to a total | Mixture | the fractions of a fuel blend |
| An order of items | Sequence | the order of jobs on one machine |
| An order of items in each of several groups | Multi-Stage Sequence | the order of jobs on each of three machines |
| An order that must obey rules of the form “A before B” | Topological Sequence | the steps of a construction project |
| An order set by attributes of the items, when the weights of the attributes are a useful result | Policy Sequence | a dispatch priority from urgency and due date |
| A route through some of a set of places | Path | a patrol route |
| Some items from a list, when a count range is the only rule | Multi-Choice | which 3 to 5 sensors to turn on |
| Some items from a list, with rules between the items | Item Selection | which sites to open, when two neighboring sites cannot both open |
| Items from a pool whose total cost stays within a budget | Budgeted Selection | which projects to fund |
| One bin for each item | Assignment | nurses to wards |
| Items into a set number of groups that have no labels | Partition | customers into 4 delivery zones |
| A set of one-way links with no loop, optionally from a start node to an end node | DAG | dependencies between tasks |
| A hierarchy that connects every node, optionally under a fixed root | Tree | a reporting structure under the head office |
| A direction in a plane | Angle | the yaw of a turbine |
| A direction in three dimensions | Spherical Angle | the pointing direction of an antenna |
| A point inside an area on a plane or on the Earth | Region or Spherical Region | a well site inside a lease boundary |
| A long list or a large table of numbers in which neighboring values are close | a smooth type (see § Special Purpose: Smooth below) | an hourly pumping schedule |
| A random input that the optimizer does not choose | a random variable type (see § Random below) | the daily demand |
These types are close to each other:
- Sequence and Permutation give the same ranks, from 1 to n. The Permutation Variable is deprecated, so use Sequence. In an optimization,
Predictrefuses a model that has a Permutation Variable and accepts a model that has a Sequence Variable. In Adaptive Sampling,Predictaccepts both. - Choice and Design give the same values, from 1 to the number of options. The Design Variable is deprecated, so use Choice.
- Choice, Enumeration and Tuple each select one entry. A Choice Variable reports the number of the option. An Enumeration Variable reports the number from your list. A Tuple Variable reports the number of the row, and the optimizer treats rows with close values as similar options.
- Multi-Choice, Item Selection and Budgeted Selection each select several items. If there are rules between the items, such as “if item 1 is selected, you can’t pick item 2 or 3”, use Item Selection. If the only rule is a count range, such as “pick 3 to 5”, the engine finds the best selection sooner with Multi-Choice. A Multi-Choice Variable uses the names that you give, and an Item Selection Variable numbers the candidates from 1. A Budgeted Selection Variable adds a cost for each candidate and a budget. The Selection Variable in § Variable Modifiers is different: it is one on/off flag for a group of other variables.
- Assignment and Partition each put items into groups. An Assignment Variable puts each item into a numbered bin, and bin 2 is a different bin from bin 3. A Partition Variable puts the items into groups that have no labels, so the engine reports one numbering for each division of the items into groups.
- Tree, DAG and Path each give a set of links between nodes. A Tree Variable connects every node, and it has one root, which you can fix. A DAG Variable allows any set of links that has no loop, including no links at all; with a start node, an end node and the connected option, it allows only graphs that run from the start node to the end node. Both types accept precedences. A Path Variable gives one route with no branches.
- Sequence and Topological Sequence each give an order. A Sequence Variable allows any order. A Topological Sequence Variable allows only the orders that obey your “A before B” rules.
Standard
Each function adds one decision variable named name.
Add Continuous Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddContinuousVariable(String name, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddContinuousVariable(string name, double min, double max) |
| C++ | bool OptQuestModel::AddContinuousVariable(const char* name, double min, double max) |
| C | int OQAddContinuousVariable(HOptQuestModel model, const char* name, double min, double max) |
| Python | bool OptQuestModel.add_continuous_variable(str name, float min_val, float max_val) |
Description
Adds a continuous variable with the inclusive bounds min and max.
Add Integer Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddIntegerVariable(String name, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddIntegerVariable(string name, double min, double max) |
| C++ | bool OptQuestModel::AddIntegerVariable(const char* name, double min, double max) |
| C | int OQAddIntegerVariable(HOptQuestModel model, const char* name, double min, double max) |
| Python | bool OptQuestModel.add_integer_variable(str name, float min_val, float max_val) |
Description
Adds an integer variable whose values are the integers from min to max inclusive.
Add Discrete Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddDiscreteVariable(String name, double min, double max, double step) throws COptQuestException |
| C# | bool OptQuestModel.AddDiscreteVariable(string name, double min, double max, double step) |
| C++ | bool OptQuestModel::AddDiscreteVariable(const char* name, double min, double max, double step) |
| C | int OQAddDiscreteVariable(HOptQuestModel model, const char* name, double min, double max, double step) |
| Python | bool OptQuestModel.add_discrete_variable(str name, float min_val, float max_val, float step) |
Description
Adds a discrete variable whose values run from min to max inclusive in steps of step. The range must hold a whole number of steps.
Add Binary Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBinaryVariable(String name) throws COptQuestException |
| C# | bool OptQuestModel.AddBinaryVariable(string name) |
| C++ | bool OptQuestModel::AddBinaryVariable(const char* name) |
| C | int OQAddBinaryVariable(HOptQuestModel model, const char* name) |
| Python | bool OptQuestModel.add_binary_variable(str name) |
Description
Adds a binary variable whose value is 0 or 1.
Add Design Variable
Deprecated. Use the Choice Variable (§ Add Choice Variable) instead. It gives the number of the selected option, from 1 to the number of options.
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddDesignVariable(String name, int num) throws COptQuestException |
| C# | bool OptQuestModel.AddDesignVariable(string name, int num) |
| C++ | bool OptQuestModel::AddDesignVariable(const char* name, int num) |
| C | int OQAddDesignVariable(HOptQuestModel model, const char* name, int num) |
| Python | bool OptQuestModel.add_design_variable(str name, int num) |
Description
Adds a design variable with num distinct choices. Its value is an index from 1 to num; for example, the indices 1, 2 and 3 can stand for the options red, blue and green.
Add Enumeration Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddEnumerationVariable(String name, double[] items) throws COptQuestException |
| C# | bool OptQuestModel.AddEnumerationVariable(string name, double[] items) |
| C++ | bool OptQuestModel::AddEnumerationVariable(const char* name, const double* items, int n) |
| C | int OQAddEnumerationVariable(HOptQuestModel model, const char* name, const double* items, int n) |
| Python | bool OptQuestModel.add_enumeration_variable(str name, list[float] values) |
Description
Adds an enumeration variable whose value is one of the numbers in items.
Notes
- In C and C++,
itemsis a pointer to an array ofndoubles.
Add Tuple Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddTupleVariable(String name, double[][] tuples) throws COptQuestException |
| C# | bool OptQuestModel.AddTupleVariable(string name, double[][] tuples) |
| C++ | bool OptQuestModel::AddTupleVariable(const char* name, const double** tuples, int nt, int nv) |
| C | int OQAddTupleVariable(HOptQuestModel model, const char* name, const double** tuples, int nt, int nv) |
| Python | bool OptQuestModel.add_tuple_variable(str name, list[list[float]] tuples) |
Description
Adds a tuple variable that selects one of the tuples in tuples. The value the solution reports is the 1-based index of the selected tuple. Each tuple is a point in n-dimensional space, and the optimizer uses the Euclidean distance between tuples to judge which choices are close to each other.
Notes
- In C and C++,
tuplesis a pointer to an array ofnttuples, each a pointer tonvdoubles.
Add Geolocation Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddGeolocationVariable(String name, double[][] locations) throws COptQuestException |
| C# | bool OptQuestModel.AddGeolocationVariable(string name, double[][] locations) |
| C++ | bool OptQuestModel::AddGeolocationVariable(const char* name, const double** locations, int nl) |
| C | int OQAddGeolocationVariable(HOptQuestModel model, const char* name, const double** locations, int nl) |
| Python | bool OptQuestModel.add_geolocation_variable(str name, list[list[float]] locations) |
Description
Adds a geolocation variable that selects one of the (latitude, longitude) pairs in locations. The value the solution reports is the 1-based index of the selected pair. The optimizer uses the angular distance between locations on a sphere to judge which choices are close to each other.
Notes
- In C and C++,
locationsis a pointer to an array ofnlpairs, each a pointer to 2 doubles.
Container
A container function creates one independent standard variable per element and registers each one with the engine as an ordinary input variable. The elements share the bounds (and, for the discrete forms, the step) that you pass. They behave the same as variables added one at a time, and there is no performance cost compared with adding them one at a time. Use a container when many similar variables belong together (weights, coefficients, coordinates, grid parameters) and you want less code and uniform names.
Element names are 1-based and, for two or more dimensions, row-major:
| Shape | Element names |
|---|---|
Vector of n |
<name>@1 … <name>@n |
Matrix m×n |
<name>@<row>,<col>, from <name>@1,1 to <name>@m,n |
ND with dims |
<name>@i1,i2,…,ir; element [2,1,3] of a [3,4,2] array is <name>@2,1,3 |
Every dimension must be at least 1, and dims must not be empty. Use the ND form when the decision has more than two dimensions, or when you want the same indexing style for every rank. In an expression, write a name that contains a comma in square brackets, [<name>@1,2], so that the comma is not read as an argument separator. In C and C++, dims is a pointer to an array of ndims ints.
Add Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddVectorVariable(String name, int n, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddVectorVariable(string name, int n, double min, double max) |
| C++ | bool OptQuestModel::AddVectorVariable(const char* name, int n, double min, double max) |
| C | int OQAddVectorVariable(HOptQuestModel model, const char* name, int n, double min, double max) |
| Python | bool OptQuestModel.add_vector_variable(str name, int n, float min_val, float max_val) |
Description
Adds a vector variable: n continuous variables. The elements are ordinary input variables.
Each element holds a continuous value from min to max.
Notes
- Variable names:
<name>@1to<name>@n, one for each element.
Add Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddMatrixVariable(String name, int m, int n, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddMatrixVariable(string name, int m, int n, double min, double max) |
| C++ | bool OptQuestModel::AddMatrixVariable(const char* name, int m, int n, double min, double max) |
| C | int OQAddMatrixVariable(HOptQuestModel model, const char* name, int m, int n, double min, double max) |
| Python | bool OptQuestModel.add_matrix_variable(str name, int m, int n, float min_val, float max_val) |
Description
Adds a matrix variable: an m by n matrix of continuous variables. The elements are ordinary input variables.
Each element holds a continuous value from min to max.
Notes
- Variable names:
<name>@<row>,<col>for each element, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2].
Add ND Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddNDVariable(String name, int[] dims, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddNDVariable(string name, int[] dims, double min, double max) |
| C++ | bool OptQuestModel::AddNDVariable(const char* name, const int* dims, int ndims, double min, double max) |
| C | int OQAddNDVariable(HOptQuestModel model, const char* name, const int* dims, int ndims, double min, double max) |
| Python | bool OptQuestModel.add_nd_variable(str name, list[int] dims, float min_val, float max_val) |
Description
Adds an N-dimensional variable: an array of continuous variables with the shape dims. The elements are ordinary input variables.
Each element holds a continuous value from min to max.
Notes
- Variable names:
<name>@<i1>,<i2>,...for each element, with one 1-based index for each dimension. The last index changes fastest. With two or more dimensions, each name contains a comma, so write it in brackets in an expression:[<name>@1,2,3].
Add Integer Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddIntegerVectorVariable(String name, int n, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddIntegerVectorVariable(string name, int n, double min, double max) |
| C++ | bool OptQuestModel::AddIntegerVectorVariable(const char* name, int n, double min, double max) |
| C | int OQAddIntegerVectorVariable(HOptQuestModel model, const char* name, int n, double min, double max) |
| Python | bool OptQuestModel.add_integer_vector_variable(str name, int n, float min_val, float max_val) |
Description
Adds an integer vector variable: n integer variables. The elements are ordinary input variables.
Each element takes the values min, min + 1, min + 2, and so on, up to max. Give whole-number bounds to get whole-number values.
Notes
- Variable names:
<name>@1to<name>@n, one for each element.
Add Integer Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddIntegerMatrixVariable(String name, int m, int n, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddIntegerMatrixVariable(string name, int m, int n, double min, double max) |
| C++ | bool OptQuestModel::AddIntegerMatrixVariable(const char* name, int m, int n, double min, double max) |
| C | int OQAddIntegerMatrixVariable(HOptQuestModel model, const char* name, int m, int n, double min, double max) |
| Python | bool OptQuestModel.add_integer_matrix_variable(str name, int m, int n, float min_val, float max_val) |
Description
Adds an integer matrix variable: an m by n matrix of integer variables. The elements are ordinary input variables.
Each element takes the values min, min + 1, min + 2, and so on, up to max. Give whole-number bounds to get whole-number values.
Notes
- Variable names:
<name>@<row>,<col>for each element, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2].
Add Integer ND Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddIntegerNDVariable(String name, int[] dims, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddIntegerNDVariable(string name, int[] dims, double min, double max) |
| C++ | bool OptQuestModel::AddIntegerNDVariable(const char* name, const int* dims, int ndims, double min, double max) |
| C | int OQAddIntegerNDVariable(HOptQuestModel model, const char* name, const int* dims, int ndims, double min, double max) |
| Python | bool OptQuestModel.add_integer_nd_variable(str name, list[int] dims, float min_val, float max_val) |
Description
Adds an integer N-dimensional variable: an array of integer variables with the shape dims. The elements are ordinary input variables.
Each element takes the values min, min + 1, min + 2, and so on, up to max. Give whole-number bounds to get whole-number values.
Notes
- Variable names:
<name>@<i1>,<i2>,...for each element, with one 1-based index for each dimension. The last index changes fastest. With two or more dimensions, each name contains a comma, so write it in brackets in an expression:[<name>@1,2,3].
Add Discrete Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddDiscreteVectorVariable(String name, int n, double min, double max, double step) throws COptQuestException |
| C# | bool OptQuestModel.AddDiscreteVectorVariable(string name, int n, double min, double max, double step) |
| C++ | bool OptQuestModel::AddDiscreteVectorVariable(const char* name, int n, double min, double max, double step) |
| C | int OQAddDiscreteVectorVariable(HOptQuestModel model, const char* name, int n, double min, double max, double step) |
| Python | bool OptQuestModel.add_discrete_vector_variable(str name, int n, float min_val, float max_val, float step) |
Description
Adds a discrete vector variable: n discrete variables. The elements are ordinary input variables.
Each element takes the values min, min + step, min + 2 × step, and so on. The largest value is the one nearest to max, so it can differ from max when max - min is not a whole multiple of step.
Notes
- Variable names:
<name>@1to<name>@n, one for each element. step: step between values; must be greater than 0.
Add Discrete Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddDiscreteMatrixVariable(String name, int m, int n, double min, double max, double step) throws COptQuestException |
| C# | bool OptQuestModel.AddDiscreteMatrixVariable(string name, int m, int n, double min, double max, double step) |
| C++ | bool OptQuestModel::AddDiscreteMatrixVariable(const char* name, int m, int n, double min, double max, double step) |
| C | int OQAddDiscreteMatrixVariable(HOptQuestModel model, const char* name, int m, int n, double min, double max, double step) |
| Python | bool OptQuestModel.add_discrete_matrix_variable(str name, int m, int n, float min_val, float max_val, float step) |
Description
Adds a discrete matrix variable: an m by n matrix of discrete variables. The elements are ordinary input variables.
Each element takes the values min, min + step, min + 2 × step, and so on. The largest value is the one nearest to max, so it can differ from max when max - min is not a whole multiple of step.
Notes
- Variable names:
<name>@<row>,<col>for each element, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. step: step between values; must be greater than 0.
Add Discrete ND Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddDiscreteNDVariable(String name, int[] dims, double min, double max, double step) throws COptQuestException |
| C# | bool OptQuestModel.AddDiscreteNDVariable(string name, int[] dims, double min, double max, double step) |
| C++ | bool OptQuestModel::AddDiscreteNDVariable(const char* name, const int* dims, int ndims, double min, double max, double step) |
| C | int OQAddDiscreteNDVariable(HOptQuestModel model, const char* name, const int* dims, int ndims, double min, double max, double step) |
| Python | bool OptQuestModel.add_discrete_nd_variable(str name, list[int] dims, float min_val, float max_val, float step) |
Description
Adds a discrete N-dimensional variable: an array of discrete variables with the shape dims. The elements are ordinary input variables.
Each element takes the values min, min + step, min + 2 × step, and so on. The largest value is the one nearest to max, so it can differ from max when max - min is not a whole multiple of step.
Notes
- Variable names:
<name>@<i1>,<i2>,...for each element, with one 1-based index for each dimension. The last index changes fastest. With two or more dimensions, each name contains a comma, so write it in brackets in an expression:[<name>@1,2,3]. step: step between values; must be greater than 0.
Add Binary Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBinaryVectorVariable(String name, int k) throws COptQuestException |
| C# | bool OptQuestModel.AddBinaryVectorVariable(string name, int k) |
| C++ | bool OptQuestModel::AddBinaryVectorVariable(const char* name, int k) |
| C | int OQAddBinaryVectorVariable(HOptQuestModel model, const char* name, int k) |
| Python | bool OptQuestModel.add_binary_vector_variable(str name, int k) |
Description
Adds a binary vector variable: k binary variables. The elements are ordinary input variables.
Each element holds 0 or 1.
Notes
- Variable names:
<name>@1to<name>@k, one for each element.
Add Binary Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBinaryMatrixVariable(String name, int m, int n) throws COptQuestException |
| C# | bool OptQuestModel.AddBinaryMatrixVariable(string name, int m, int n) |
| C++ | bool OptQuestModel::AddBinaryMatrixVariable(const char* name, int m, int n) |
| C | int OQAddBinaryMatrixVariable(HOptQuestModel model, const char* name, int m, int n) |
| Python | bool OptQuestModel.add_binary_matrix_variable(str name, int m, int n) |
Description
Adds a binary matrix variable: an m by n matrix of binary variables. The elements are ordinary input variables.
Each element holds 0 or 1.
Notes
- Variable names:
<name>@<row>,<col>for each element, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2].
Add Binary ND Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBinaryNDVariable(String name, int[] dims) throws COptQuestException |
| C# | bool OptQuestModel.AddBinaryNDVariable(string name, int[] dims) |
| C++ | bool OptQuestModel::AddBinaryNDVariable(const char* name, const int* dims, int ndims) |
| C | int OQAddBinaryNDVariable(HOptQuestModel model, const char* name, const int* dims, int ndims) |
| Python | bool OptQuestModel.add_binary_nd_variable(str name, list[int] dims) |
Description
Adds a binary N-dimensional variable: an array of binary variables with the shape dims. The elements are ordinary input variables.
Each element holds 0 or 1.
Notes
- Variable names:
<name>@<i1>,<i2>,...for each element, with one 1-based index for each dimension. The last index changes fastest. With two or more dimensions, each name contains a comma, so write it in brackets in an expression:[<name>@1,2,3].
Permutation
A permutation variable is an ordinary decision variable. The position variables it creates are the values that the optimizer sets and the simulator reads. It is in its own family and is not one of the special purpose variables. Its element names use the same @ notation as theirs.
Add Permutation Variable
Deprecated. Use the Sequence Variable (§ Add Sequence Variable) instead. It gives the same ranks, from 1 to n, under element names of the same form, and it also has a top-k mode.
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddPermutationVariable(String group, String[] names) throws COptQuestException |
| C# | bool OptQuestModel.AddPermutationVariable(string group, string[] names) |
| C++ | bool OptQuestModel::AddPermutationVariable(const char* group, const char** names, int n) |
| C | int OQAddPermutationVariable(HOptQuestModel model, const char* group, const char** names, int n) |
| Python | bool OptQuestModel.add_permutation_variable(str group, list[str] names) |
Description
Adds a permutation variable named group over the elements in names. The engine creates one integer decision variable per element, named <group>@<name>. Its value is the position of that element in the order, from 1 to n. Every trial solution is a complete permutation: each position appears exactly once. The strings in names must be distinct.
Example
model.AddPermutationVariable("group", new String[]{"a","b","c"});This creates three decision variables: group@a, group@b and group@c. In the generate step, OptQuest writes the position of each element into its variable. If group@a = 1, group@b = 3 and group@c = 2, the evaluator must compute its outputs for the order {a, c, b}.
Notes
- In C and C++,
namesis a pointer to an array ofnstrings.
Special Purpose Variables: Common Behavior
A special purpose variable is a decision variable whose values must stay inside a structured set, for example an angle on an arc, a ranking of a list of items, or a matrix of limited rank. In every solution that the engine generates, and in every suggested solution, the values of a special purpose variable are inside its set. The simulator needs no code to handle values that are not valid.
In the Java class library, COptQuestManifoldVariable is the base class of the special purpose variable types, and the Javadoc calls them manifold variables. A saved model file uses the XML element ManifoldVariable for them.
The special purpose variable types are:
- Combinatorial: Choice, Multi-Choice, Mixture, Sequence, Multi-Stage Sequence, Policy Sequence, Topological Sequence, Assignment, Item Selection, Budgeted Selection, Partition, DAG, Tree and Path.
- Geometric: Angle, Spherical Angle, Region and Spherical Region.
- Smooth: Low-Rank Matrix, Time-Series Vector, B-spline, Spline and Fourier, each with its correction variants.
The Permutation variable is in its own family and is not one of the special purpose variables. Its element names use the same @ notation as theirs. See § API Documentation › Decision Variables › Add Permutation Variable.
Variable Names
A special purpose variable creates its variables under generated names of the form <name>@<suffix>, where <name> is the base name. The Notes of each type list the variable names and the values they hold. Use these names, not the base name, in expressions, objectives and constraints. See § Concepts › Names.
GetInputNames returns the variable names of every special purpose variable, because they are inputs: the engine sets them, and the evaluator reads them. The exceptions are the coefficient, contribution and confidence names of a policy sequence variable, whose values the engine computes. GetOutputNames returns those.
The variable names of the Item Selection and Budgeted Selection variables are ordinary binary inputs: the engine chooses these values directly. The engine adds the rules of these two types and of the Assignment variable to the model as constraints, so a solution that breaks a rule is infeasible.
Evaluated and Required Solutions
The engine uses the values of the special purpose variables in an evaluated solution or a required solution as given, so supply values that are inside the set of each variable. In a suggested solution, the engine can change values that are not inside the set.
Constraint Enforcement Timing
The engine checks a constraint over the variable names of a special purpose variable, other than an Item Selection or a Budgeted Selection variable, after evaluation, the same way it checks a constraint over an output. The simulator always receives values that follow the rules of the variable type. Only the constraint check is deferred. A solution that breaks such a constraint is marked infeasible after its evaluation, so it costs a full evaluation.
When the declaration of the variable can express a restriction, declare it there: an arc on an Angle Variable, per-component bounds and sumTo on a Mixture Variable, a count or capacity range on a selection or assignment type. A restriction declared that way holds for every solution that the engine generates, and it costs no evaluation. Use a constraint over the variable names only when the declaration cannot express the rule.
The Notes of each type below list only what is specific to that type. The behavior in this section applies to every special purpose variable.
Special Purpose: Combinatorial
Add Choice Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddChoiceVariable(String name, int k) throws COptQuestException |
| C# | bool OptQuestModel.AddChoiceVariable(string name, int k) |
| C++ | bool OptQuestModel::AddChoiceVariable(const char* name, int k) |
| C | int OQAddChoiceVariable(HOptQuestModel model, const char* name, int k) |
| Python | bool OptQuestModel.add_choice_variable(str name, int k) |
Description
Adds a choice variable. Its value is one option out of k options. Use a choice variable when the decision is one selection from options that have no natural order, such as a machine type, a supplier or an operating mode.
In every solution that the engine generates, exactly one option is selected.
In a suggested solution, the engine rounds the value to the nearest whole number from 1 to k.
Notes
- Variable names:
<name>@choice, the 1-based index of the selected option, a whole number from 1 tok. - The Choice Variable replaces the Design Variable, which is deprecated; see § API Documentation › Decision Variables › Add Design Variable.
Add Multi-Choice Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddMultiChoiceVariable(String name, String[] choices, int minSelect, int maxSelect) throws COptQuestException |
| C# | bool OptQuestModel.AddMultiChoiceVariable(string name, string[] choices, int minSelect, int maxSelect) |
| C++ | bool OptQuestModel::AddMultiChoiceVariable(const char* name, const char** choices, int numChoices, int minSelect, int maxSelect) |
| C | int OQAddMultiChoiceVariable(HOptQuestModel model, const char* name, const char** choices, int numChoices, int minSelect, int maxSelect) |
| Python | bool OptQuestModel.add_multi_choice_variable(str name, list[str] choices, int min_select, int max_select) |
Description
Adds a multi-choice variable. Its value is a subset of the choices that has from minSelect to maxSelect members. Use a multi-choice variable when the decision is an unordered selection of several items and a count range is the only rule, such as which sensors to turn on or which assets to include. If there are rules between the items, use the Item Selection Variable (§ Add Item Selection Variable).
In every solution that the engine generates, each choice is either selected or not, and the number of selected choices is from minSelect to maxSelect.
In a suggested solution, the engine selects each choice whose value is greater than 0.5. If the suggested solution selects more than maxSelect choices, the engine keeps the selected choices that come first in choices. If it selects fewer than minSelect, the engine adds the unselected choices that come first.
Notes
- Variable names:
<name>@<choice>for each choice, in the order ofchoices. Each holds 1 if the choice is selected and 0 if it is not. - In C and C++,
choicesis a pointer to an array ofnumChoicesstrings.
Add Mixture Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddMixtureVariable(String name, String[] components, double[] lowerBounds, double[] upperBounds, double sumTo) throws COptQuestException |
| C# | bool OptQuestModel.AddMixtureVariable(string name, string[] components, double[]? lowerBounds, double[]? upperBounds, double sumTo) |
| C++ | bool OptQuestModel::AddMixtureVariable(const char* name, const char** components, int k, const double* lowerBounds, const double* upperBounds, double sumTo) |
| C | int OQAddMixtureVariable(HOptQuestModel model, const char* name, const char** components, int k, const double* lowerBounds, const double* upperBounds, double sumTo) |
| Python | bool OptQuestModel.add_mixture_variable(str name, list[str] components, list[float] lower_bounds=None, list[float] upper_bounds=None, float sum_to=1.0) |
Description
Adds a mixture variable. Its value is a set of continuous weights, one for each component, and the weights sum to sumTo. Use a mixture variable when the decision is a set of proportions, such as portfolio weights, blend fractions or allocation ratios.
In every solution that the engine generates, the weights sum to sumTo within 1e-12, and each weight is within the bounds of its component.
With a negative lower bound, the weights can go below zero, down to that bound.
Notes
- Variable names:
<name>@<component>for each component, in the order ofcomponents. Each holds the weight of that component. sumTomust be greater than zero.lowerBoundsandupperBoundsare optional in every language and form a matched pair: supply both (each of lengthk) or neither (null,NULLorNone). The call fails if only one is supplied.- In C and C++,
componentsis a pointer to an array ofkstrings;lowerBoundsandupperBoundsare each a pointer to an array ofkdoubles.
Add Sequence Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSequenceVariable(String name, String[] components, Integer topK) throws COptQuestException |
| C# | bool OptQuestModel.AddSequenceVariable(string name, string[] components, int? topK = null) |
| C++ | bool OptQuestModel::AddSequenceVariable(const char* name, const char** components, int k, const int* topK) |
| C | int OQAddSequenceVariable(HOptQuestModel model, const char* name, const char** components, int k, const int* topK) |
| Python | bool OptQuestModel.add_sequence_variable(str name, list[str] components, int top_k=None) |
Description
Adds a sequence variable. Its value is a priority order of the components. Use a sequence variable when the decision is an order of discrete items, such as a job sequence or the priority of sensor tasks.
In every solution that the engine generates, the ranks are valid. In a full ranking, the values are a permutation of 1 to n, where n is the number of components and 1 is the highest priority. In a top-k ranking, the first topK components get the ranks 1 to topK, and every other component gets the rank topK + 1.
When a suggested solution gives two components the same rank, the component that comes first in components gets the better rank.
Notes
- Variable names:
<name>@<component>for each component, in the order ofcomponents. Each holds the integer rank of that component. topK: null for a full ranking, or the number of components to rank. A value of n or more gives a full ranking, and a value less than 1 is used as 1. WithtopK= 1, the most important component gets rank 1, and every other component gets rank 2.- In Java, pass
nullfortopKto request a full ranking. In C#, passnull(the parameter type isint?). In Python, omittop_kor passNone. In C and C++,topKis a pointer to a singleint; passNULLfor a full ranking. - In C and C++,
componentsis a pointer to an array ofkstrings. - The Sequence Variable replaces the Permutation Variable, which is deprecated; see § API Documentation › Decision Variables › Add Permutation Variable.
Add Multi-Stage Sequence Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddMultiStageSequenceVariable(String name, String[][] stageGroups) throws COptQuestException |
| C# | bool OptQuestModel.AddMultiStageSequenceVariable(string name, string[][] stageGroups) |
| C++ | bool OptQuestModel::AddMultiStageSequenceVariable(const char* name, const char*** stageGroups, int numStages, const int* stageSizes) |
| C | int OQAddMultiStageSequenceVariable(HOptQuestModel model, const char* name, const char*** stageGroups, int numStages, const int* stageSizes) |
| Python | bool OptQuestModel.add_multi_stage_sequence_variable(str name, list[list[str]] stage_groups) |
Description
Adds a multi-stage sequence variable. Its value is one priority order for each stage, over the components of that stage. Use a multi-stage sequence variable when the decision is a set of orders, one for each stage, such as the job order on each of several machines.
In every solution that the engine generates, the ranks in each stage are a permutation of 1 to the number of components in that stage, where 1 is the highest priority. The engine ranks each stage separately.
A component name can appear in only one stage. To rank the same item in two stages, give it a different name in each stage.
When a suggested solution gives two components of a stage the same rank, the component that comes first in that stage gets the better rank.
Notes
- Variable names:
<name>@<component>for every component, stage by stage, in the order ofstageGroups. Each holds the integer rank of that component within its stage. - In C and C++,
stageGroupsis a pointer to an array ofnumStagesstages, each a pointer to its own array of component name strings, andstageSizesis a pointer to an array ofnumStagesints that gives the size of each stage.
Add Policy Sequence Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddPolicySequenceVariable(String name, double[][] featureMatrix, String[] itemNames, String[] featureNames) throws COptQuestException |
| C# | bool OptQuestModel.AddPolicySequenceVariable(string name, double[][] featureMatrix, string[] itemNames, string[] featureNames) |
| C++ | bool OptQuestModel::AddPolicySequenceVariable(const char* name, const double** featureMatrix, int n, int k, const char** itemNames, const char** featureNames) |
| C | int OQAddPolicySequenceVariable(HOptQuestModel model, const char* name, const double** featureMatrix, int n, int k, const char** itemNames, const char** featureNames) |
| Python | bool OptQuestModel.add_policy_sequence_variable(str name, list[list[float]] feature_matrix, list[str] item_names, list[str] feature_names) |
Description
Adds a policy sequence variable. Its value is a linear scoring rule over the features of a set of items: one weight for each feature, and a priority score for each item. Use a policy sequence variable when a good order depends on a few item attributes, and the weights themselves are a useful result, for example dispatch order by urgency and setup family.
In every solution that the engine generates, the item scores come from one set of feature weights applied to the feature matrix. Sort the items by descending score to get the ranked list: a higher score means a higher priority. This is the opposite of a sequence variable, where 1 is the highest priority.
The engine computes every value of a policy sequence variable. The item scores are inputs. The coefficients, the contributions and the confidences are outputs. The five families of names are in the Notes. Item names and feature names share one set of names, so every item name and feature name must be different from all the others.
Give the feature values in their own units. The engine scales the columns, so you do not need to scale them. In a suggested solution, the engine reads only the item scores, and it can change them. For an evaluated or required solution, the engine computes the coefficient, contribution and confidence outputs from the policy that best fits the supplied item scores. It does not change the scores.
Each item name and feature name must not contain whitespace, a semicolon, a comma or @.
Notes
- Variable names:
<name>@<itemName>for each item, an input: the priority score of that item.<name>@<featureName>for each feature, an output: the coefficient of that feature, which is the change in score for one unit of the feature. Multiply each raw feature value of an item by its coefficient and add the products to score a new item. That sum can differ from the reported score by a constant that is the same for every item, so it gives the same order.<name>@<featureName>@contributionfor each feature, an output: the signed share of that feature in the rule, in [-1, 1]. The absolute values of all the contributions sum to 1.<name>@<featureName>@confidencefor each feature, an output: a confidence in [0, 1] for the weight of that feature. A feature whose values are all equal gets 0.<name>@<itemName>@confidencefor each item, an output: a confidence in [0, 1] that the item is in the right place relative to its neighbors in the order. With one item, the value is 1.
- In C and C++,
featureMatrixis a pointer to an array ofnrows, each a pointer to an array ofkdoubles;nis the item count (rows) andkis the feature count (columns).itemNameshas lengthnandfeatureNameshas lengthk. In Java, C# and Python the counts come from the supplied matrix and name arrays.
Add Topological Sequence Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddTopologicalSequenceVariable(String name, String[] tasks, Map<String, List<String>> predecessors) throws COptQuestException |
| C# | bool OptQuestModel.AddTopologicalSequenceVariable(string name, string[] tasks, Dictionary<string, List<string>> predecessors) |
| C++ | bool OptQuestModel::AddTopologicalSequenceVariable(const char* name, const char* tasks[], int numTasks, const char* predecessors[][2], int numPairs) |
| C | int OQAddTopologicalSequenceVariable(HOptQuestModel model, const char* name, const char* tasks[], int numTasks, const char* predecessors[][2], int numPairs) |
| Python | bool OptQuestModel.add_topological_sequence_variable(str name, list[str] tasks, dict[str, list[str]] predecessors) |
Description
Adds a topological sequence variable. Its value is an order of the tasks in which every task comes after its predecessors. Use a topological sequence variable when the decision is the order in which to do a set of tasks, and some tasks must always come before others, such as project steps with dependencies or an assembly sequence.
In every solution that the engine generates, the order keeps every precedence: a predecessor always has a smaller rank than the task that depends on it.
In a suggested solution, the engine keeps an order that meets every precedence, and it gives equal ranks different values in the order of tasks. If the order breaks a precedence, the engine changes it: at each step, of the tasks that can go next, the task with the smallest suggested rank goes next.
The engine checks that no task lists itself as a predecessor and that the precedences form no cycle. It ignores names in predecessors that are not in tasks.
predecessors gives the dependencies. In Java, C# and Python it is a map from a dependent task to the list of tasks that must finish before it. In C and C++ it is an array of [dependent, predecessor] pairs; a task with several predecessors appears in several pairs.
Notes
- Variable names:
<name>@<task>for each task, in the order oftasks. Each holds the integer rank of that task in the order, where 1 is first and n is last. The ranks are a permutation of 1 to n. - In C and C++,
tasksis a pointer to an array ofnumTasksstrings, andpredecessorsis a pointer to an array ofnumPairstwo-element string pairs.
Add Assignment Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddAssignmentVariable(String name, int m, int n) throws COptQuestException boolean OptQuestModel.AddAssignmentVariable(String name, int m, int n, boolean mustAssign, int binCapacityMin, int binCapacityMax) throws COptQuestException boolean OptQuestModel.AddAssignmentVariable(String name, int m, int n, boolean[] mustAssign, int[] binCapacitiesMin, int[] binCapacitiesMax) throws COptQuestException |
| C# | bool OptQuestModel.AddAssignmentVariable(string name, int m, int n) bool OptQuestModel.AddAssignmentVariable(string name, int m, int n, bool mustAssign, int binCapacityMin, int binCapacityMax) bool OptQuestModel.AddAssignmentVariable(string name, int m, int n, bool[] mustAssign, int[] binCapacitiesMin, int[] binCapacitiesMax) |
| C++ | bool OptQuestModel::AddAssignmentVariable(const char* name, int m, int n) bool OptQuestModel::AddAssignmentVariable(const char* name, int m, int n, bool mustAssign, int binCapacityMin, int binCapacityMax) bool OptQuestModel::AddAssignmentVariable(const char* name, int m, int n, const bool* mustAssign, const int* binCapacitiesMin, const int* binCapacitiesMax) |
| C | int OQAddAssignmentVariable(HOptQuestModel model, const char* name, int m, int n) int OQAddAssignmentVariableHom(HOptQuestModel model, const char* name, int m, int n, int mustAssign, int binCapacityMin, int binCapacityMax) int OQAddAssignmentVariableHet(HOptQuestModel model, const char* name, int m, int n, const int* mustAssign, const int* binCapacitiesMin, const int* binCapacitiesMax) |
| Python | bool OptQuestModel.add_assignment_variable(str name, int m, int n, must_assign=None, bin_capacity_min=0, bin_capacity_max=None) |
Description
Adds an assignment variable. Its value is an assignment of each of m items to one of n bins. Use an assignment variable when the decision assigns items to bins, such as jobs to machines or tasks to workers. Three overloads set the rules:
- Simple
(name, m, n): every item is in exactly one bin, and a bin can hold any number of items. - Homogeneous
(name, m, n, mustAssign, binCapacityMin, binCapacityMax): whenmustAssignis true, every item is in exactly one bin, and when it is false, every item is in at most one bin. Every bin holds frombinCapacityMintobinCapacityMaxitems. - Heterogeneous
(name, m, n, mustAssign[], binCapacitiesMin[], binCapacitiesMax[]): itemiis in exactly one bin whenmustAssign[i]is true, and in at most one bin when it is false. Binjholds frombinCapacitiesMin[j]tobinCapacitiesMax[j]items.
The engine adds the assignment rules to the model as constraints, so a solution that breaks a rule is infeasible.
In a suggested solution, the engine rounds each value to the nearest bin index, and it puts an item whose value is outside 1 to n in no bin. The engine can then change the assignment so that it meets the rules.
In Python, one method covers the three forms: omit must_assign for the simple form, pass a bool or int for the homogeneous form, or pass a sequence for the heterogeneous form.
In C, the homogeneous function takes mustAssign as an int (0 = false, non-zero = true), and the heterogeneous function takes the flags as const int* with the same convention.
Notes
- Variable names:
<name>@1to<name>@m, one for each item. Each holds the 1-based index of the bin that holds the item, or 0 when the item is in no bin, which can happen only when the item does not have to be assigned. m(items) andn(bins) must each be at least 1.- The call fails if a bin maximum is negative or less than its minimum, if the bin minimums add up to more than
mitems, or if the bins cannot hold every item that must be assigned. - In C and C++, for the heterogeneous overload,
mustAssignis a pointer to an array ofmflags, andbinCapacitiesMinandbinCapacitiesMaxare each a pointer to an array ofnints.
Add Item Selection Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddItemSelectionVariable(String name, int n, int k) throws COptQuestException boolean OptQuestModel.AddItemSelectionVariable(String name, int n, int kMin, int kMax) throws COptQuestException |
| C# | bool OptQuestModel.AddItemSelectionVariable(string name, int n, int k) bool OptQuestModel.AddItemSelectionVariable(string name, int n, int kMin, int kMax) |
| C++ | bool OptQuestModel::AddItemSelectionVariable(const char* name, int n, int k) bool OptQuestModel::AddItemSelectionVariable(const char* name, int n, int kMin, int kMax) |
| C | int OQAddItemSelectionVariable(HOptQuestModel model, const char* name, int n, int k) int OQAddItemSelectionVariableRange(HOptQuestModel model, const char* name, int n, int kMin, int kMax) |
| Python | bool OptQuestModel.add_item_selection_variable(str name, int n, int k, int k_max=None) |
Description
Adds an item selection variable. Its value is a selection of candidates from a pool of n. Use an item selection variable when the decision is which candidates to include, such as which sites to open. Two overloads set the number of candidates to select:
- Exact
(name, n, k): exactlykcandidates are selected. This is the range form withkMin = kMax = k. - Range
(name, n, kMin, kMax): fromkMintokMaxcandidates are selected.
The engine adds the selection rule to the model as a constraint, so a solution that selects a different number of candidates is infeasible. The variable names are ordinary binary inputs. Expressions can reference them without brackets, and the engine enforces a constraint over them before evaluation, for example sel@2 + sel@5 <= 1.
In Python, one method covers both forms: omit k_max for the exact form, or supply it for the range form with k as the minimum.
In C, the exact form is OQAddItemSelectionVariable and the range form is OQAddItemSelectionVariableRange.
Notes
- Variable names:
<name>@1to<name>@n, one for each candidate. Each holds 1 if the candidate is selected and 0 if it is not. nmust be at least 1. The call fails if no selection ofncandidates has fromkMintokMaxmembers, for example whenkis greater thannorkMinis greater thankMax.- To turn a group of variables on or off with one binary flag, use the Selection Variable (§ Variable Modifiers) instead.
Add Budgeted Selection Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBudgetedSelectionVariable(String name, int n, double[] costs, double budgetMax) throws COptQuestException boolean OptQuestModel.AddBudgetedSelectionVariable(String name, int n, double[] costs, double budgetMin, double budgetMax, int kMin, int kMax) throws COptQuestException |
| C# | bool OptQuestModel.AddBudgetedSelectionVariable(string name, int n, double[] costs, double budgetMax) bool OptQuestModel.AddBudgetedSelectionVariable(string name, int n, double[] costs, double budgetMin, double budgetMax, int kMin, int kMax) |
| C++ | bool OptQuestModel::AddBudgetedSelectionVariable(const char* name, int n, const double* costs, double budgetMax) bool OptQuestModel::AddBudgetedSelectionVariable(const char* name, int n, const double* costs, double budgetMin, double budgetMax, int kMin, int kMax) |
| C | int OQAddBudgetedSelectionVariable(HOptQuestModel model, const char* name, int n, const double* costs, double budgetMax) int OQAddBudgetedSelectionVariableFull(HOptQuestModel model, const char* name, int n, const double* costs, double budgetMin, double budgetMax, int kMin, int kMax) |
| Python | bool OptQuestModel.add_budgeted_selection_variable(str name, int n, list[float] costs, float budget_max, float budget_min=0.0, int k_min=0, int k_max=None) |
Description
Adds a budgeted selection variable. Its value is a selection of candidates from a pool of n whose total cost is within a budget. Use a budgeted selection variable when the decision is which candidates to include within a budget, such as which projects to fund. Two overloads set the rules:
- Simple
(name, n, costs, budgetMax): the total cost of the selected candidates is at mostbudgetMax. - Full
(name, n, costs, budgetMin, budgetMax, kMin, kMax): the total cost is frombudgetMintobudgetMax, and the number of selected candidates is fromkMintokMax. AbudgetMinof 0 or less sets no smallest total.
The engine adds the budget and count rules to the model as constraints, so a solution that breaks a rule is infeasible. The variable names are ordinary binary inputs, and expressions can reference them without brackets.
In Python, one method covers both forms: supply only budget_max for the simple form, or supply any non-default budget_min, k_min or k_max for the full form.
In C, the simple form is OQAddBudgetedSelectionVariable and the full form is OQAddBudgetedSelectionVariableFull.
Notes
- Variable names:
<name>@1to<name>@n, one for each candidate. Each holds 1 if the candidate is selected and 0 if it is not. nmust be at least 1, andcostsmust have one entry for each candidate. A cost can be negative.- The call fails if
budgetMaxis less than the lowest possible total cost, ifbudgetMinis positive and greater thanbudgetMaxor than the highest possible total cost, or if no selection has fromkMintokMaxcandidates. - In C and C++,
costsis a pointer to an array ofndoubles.
Add Partition Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddPartitionVariable(String name, int m, int k) throws COptQuestException |
| C# | bool OptQuestModel.AddPartitionVariable(string name, int m, int k) |
| C++ | bool OptQuestModel::AddPartitionVariable(const char* name, int m, int k) |
| C | int OQAddPartitionVariable(HOptQuestModel model, const char* name, int m, int k) |
| Python | bool OptQuestModel.add_partition_variable(str name, int m, int k) |
Description
Adds a partition variable. Its value is a division of m items into exactly k groups. The groups have no order, and no group is empty. Use a partition variable when the decision divides items into groups, such as crews into shifts or customers into delivery zones.
In every solution that the engine generates, every group has at least one item, and the same division into groups always gets the same group numbers.
In a suggested solution, the engine rounds each value to the nearest group number from 1 to k. It then fills any empty group and numbers the groups again, so the values can change.
Notes
- Variable names:
<name>@1to<name>@m, one for each item. Each holds the 1-based number of the group that holds the item. Item 1 is always in group 1. For each later item, the group number is at most one more than the largest group number among the items before it. mmust be at leastk, andkmust be at least 1.
Add DAG Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddDAGVariable(String name, String[] nodeNames) throws COptQuestException boolean OptQuestModel.AddDAGVariable(String name, String[] nodeNames, String startNode, String endNode, boolean connected, Map<String, List<String>> predecessors) throws COptQuestException |
| C# | bool OptQuestModel.AddDAGVariable(string name, string[] nodeNames) bool OptQuestModel.AddDAGVariable(string name, string[] nodeNames, string? startNode, string? endNode, bool connected = false, Dictionary<string, List<string>>? predecessors = null) |
| C++ | bool OptQuestModel::AddDAGVariable(const char* name, const char** nodeNames, int n) bool OptQuestModel::AddDAGVariable(const char* name, const char** nodeNames, int n, const char* startNode, const char* endNode, bool connected, const char* predecessors[][2], int numPairs) |
| C | int OQAddDAGVariable(HOptQuestModel model, const char* name, const char** nodeNames, int n) int OQAddDAGVariableFull(HOptQuestModel model, const char* name, const char** nodeNames, int n, const char* startNode, const char* endNode, int connected, const char* predecessors[][2], int numPairs) |
| Python | bool OptQuestModel.add_dag_variable(str name, list[str] node_names, str start_node=None, str end_node=None, bool connected=False, dict[str, list[str]] predecessors=None) |
Description
Adds a DAG variable. Its value is a directed acyclic graph (DAG) over the given nodes: a set of directed edges with no cycle. Use a DAG variable when the decision is a set of one-way links with no loop, such as dependencies between tasks or a flow network.
In every solution that the engine generates, the edges form no cycle. Without options, any DAG over the nodes can occur, including the graph with no edges. You can restrict the graphs with these options:
startNode: this node has no incoming edge.endNode: this node has no outgoing edge.connected: every node can be reached from the start node, and every node can reach the end node. It needs a start node, an end node or both. With only a start node, the rule is only about reaching the nodes from the start node, and with only an end node, it is only about reaching the end node.predecessors: a map from a node to the nodes that must come before it. No directed path runs from a node to one of its predecessors. A precedence does not add an edge.
In a suggested solution, a value greater than 0.5 is an edge. The engine keeps a suggested DAG that follows the options as it is. If the suggested edges form a cycle or break an option, the engine removes edges until the graph follows the options, and with connected it adds edges until every node is connected.
Notes
- Variable names:
<name>@<nodeFrom>,<nodeTo>for every ordered pair of nodes, including a node paired with itself: the full n by n adjacency matrix, row by row in the order ofnodeNames. Each holds 1 if the edge fromnodeFromtonodeTois present and 0 if it is not. The diagonal is always 0. Each name contains a comma, so write it in brackets in an expression:[<name>@A,B]. startNodeandendNodemay benull,NULL,Noneor an empty string: no fixed start or end.predecessorsmay be empty,null,NULLorNone. The short form without options is the same as all options unset.- The model refuses a start or end node that is not one of the nodes, a start node that is also the end node,
connectedwith no start node and no end node, a start node that has a predecessor, an end node that is a predecessor, a node that lists itself as a predecessor, and precedences that form a cycle. Names inpredecessorsthat are not nodes are ignored. In Java the Add call throwsCOptQuestException. In the other languages the model fails when it initializes. - In C and C++,
nodeNamesis a pointer to an array ofnstrings, andpredecessorsis a pointer to an array ofnumPairspairs[dependent, predecessor]; a node with several predecessors appears in several pairs. In C,connectedis 0 or 1.
Add Tree Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddTreeVariable(String name, String[] nodeNames) throws COptQuestException boolean OptQuestModel.AddTreeVariable(String name, String[] nodeNames, String rootNode, Map<String, List<String>> predecessors) throws COptQuestException |
| C# | bool OptQuestModel.AddTreeVariable(string name, string[] nodeNames) bool OptQuestModel.AddTreeVariable(string name, string[] nodeNames, string? rootNode, Dictionary<string, List<string>>? predecessors = null) |
| C++ | bool OptQuestModel::AddTreeVariable(const char* name, const char** nodeNames, int n) bool OptQuestModel::AddTreeVariable(const char* name, const char** nodeNames, int n, const char* rootNode, const char* predecessors[][2], int numPairs) |
| C | int OQAddTreeVariable(HOptQuestModel model, const char* name, const char** nodeNames, int n) int OQAddTreeVariableFull(HOptQuestModel model, const char* name, const char** nodeNames, int n, const char* rootNode, const char* predecessors[][2], int numPairs) |
| Python | bool OptQuestModel.add_tree_variable(str name, list[str] node_names, str root_node=None, dict[str, list[str]] predecessors=None) |
Description
Adds a tree variable. Its value is a directed spanning tree over the given nodes: one node is the root, every other node has exactly one incoming edge, and every node can be reached from the root. Use a tree variable when the decision is a hierarchy that connects every node, such as a cueing network or a reporting structure.
In every solution that the engine generates, the edges form a spanning tree. The tree has exactly n - 1 edges and no cycle. You can restrict the trees with these options:
rootNode: this node is the root of every tree. Without it, any node can be the root.predecessors: a map from a node to the nodes that must come before it. A node never comes above one of its predecessors: no path from the root to a predecessor passes through the node. A precedence does not make a node the parent of another.
In a suggested solution, a value greater than 0.5 is an edge. The engine keeps a suggested tree that follows the options as it is. Otherwise, the engine keeps one incoming edge for each node other than the root, and it uses a suggested edge where it can.
Notes
- Variable names:
<name>@<nodeFrom>,<nodeTo>for every ordered pair of nodes, including a node paired with itself: the full n by n adjacency matrix, row by row in the order ofnodeNames. Each holds 1 if the edge fromnodeFromtonodeTois present and 0 if it is not. The diagonal is always 0. Each name contains a comma, so write it in brackets in an expression:[<name>@A,B]. rootNodemay benull,NULL,Noneor an empty string: any node can be the root.predecessorsmay be empty,null,NULLorNone. The short form without options is the same as both options unset.- The model refuses a root that is not one of the nodes, a root that has a predecessor, a node that lists itself as a predecessor, and precedences that form a cycle. Names in
predecessorsthat are not nodes are ignored. In Java the Add call throwsCOptQuestException. In the other languages the model fails when it initializes. - In C and C++,
nodeNamesis a pointer to an array ofnstrings, andpredecessorsis a pointer to an array ofnumPairspairs[dependent, predecessor]; a node with several predecessors appears in several pairs.
Add Path Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddPathVariable(String name, String[] nodeNames, String startNode, String endNode, String[] requiredNodes) throws COptQuestException |
| C# | bool OptQuestModel.AddPathVariable(string name, string[] nodeNames, string? startNode = null, string? endNode = null, string[]? requiredNodes = null) |
| C++ | bool OptQuestModel::AddPathVariable(const char* name, const char** nodeNames, int numNodes, const char* startNode, const char* endNode, const char** requiredNodes, int nRequired) |
| C | int OQAddPathVariable(HOptQuestModel model, const char* name, const char** nodeNames, int numNodes, const char* startNode, const char* endNode, const char** requiredNodes, int nRequired) |
| Python | bool OptQuestModel.add_path_variable(str name, list[str] node_names, str start_node=None, str end_node=None, list[str] required_nodes=None) |
Description
Adds a path variable. Its value is a simple path through some of the given nodes: an order of nodes in which no node appears twice. Use a path variable when the decision is a route that visits some of the candidate nodes, such as a patrol route or a delivery tour.
In every solution that the engine generates, the path is valid. The positions of the nodes on the path are 1 to L, where L is the length of the path, with no gap and no repeat. The start node, when given, has position 1. The end node, when given and different from the start node, has position L. When the start node and the end node are the same node, it has position 1 only. Every required node is on the path. The path can have only one node.
In a suggested solution, the engine puts a node whose value is 0 or less off the path, and it uses the other values only for the order of the nodes. The engine numbers the positions again, and it adds the start node, the end node and the required nodes when they are missing.
Notes
- Variable names:
<name>@<node>for each node, in the order ofnodeNames. Each holds the 1-based position of that node on the path, or 0 if the node is not on the path. - At least two candidate nodes are required.
startNodeandendNodemay benull,NULLorNone(no fixed start or end).requiredNodesmay be empty,null,NULLorNone.- When
startNodeequalsendNode, the path does not return to the start node. The evaluator handles the return leg, for example by adding the closing edge in the objective. - In C and C++,
nodeNamesis a pointer to an array ofnumNodesstrings, andrequiredNodesis a pointer to an array ofnRequiredstrings.
Special Purpose: Geometric
A geometric variable places a point on a circle, on a sphere or inside a polygon. All angles are in degrees.
Add Angle Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddAngleVariable(String name, double minDeg, double maxDeg) throws COptQuestException |
| C# | bool OptQuestModel.AddAngleVariable(string name, double minDeg, double maxDeg) |
| C++ | bool OptQuestModel::AddAngleVariable(const char* name, double minDeg, double maxDeg) |
| C | int OQAddAngleVariable(HOptQuestModel model, const char* name, double minDeg, double maxDeg) |
| Python | bool OptQuestModel.add_angle_variable(str name, float min_deg, float max_deg) |
Description
Adds an angle variable. Its value is an angle in degrees on an arc of the circle. Use an angle variable when the decision is a direction in a plane, such as a panel orientation or a turbine yaw.
In every solution that the engine generates, the angle is on the arc from minDeg to maxDeg. When the difference between maxDeg and minDeg is 360 or more, the arc is the full circle. Otherwise the arc goes from minDeg to maxDeg in the direction of increasing angle, so an arc with minDeg greater than maxDeg, such as 320 to 40, crosses 0.
The engine reports the angle as its equivalent in [0, 360), which can differ from the range that you declare. For example, for an arc declared from -45 to 45, the engine reports 315 for -45. To compare the value with the declared bounds, first subtract 360 while the value is greater than maxDeg.
Notes
- Variable names:
<name>@theta, the angle in degrees.
Add Spherical Angle Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSphericalAngleVariable(String name, double minThetaDeg, double maxThetaDeg, double minPhiDeg, double maxPhiDeg) throws COptQuestException |
| C# | bool OptQuestModel.AddSphericalAngleVariable(string name, double minThetaDeg, double maxThetaDeg, double minPhiDeg, double maxPhiDeg) |
| C++ | bool OptQuestModel::AddSphericalAngleVariable(const char* name, double minThetaDeg, double maxThetaDeg, double minPhiDeg, double maxPhiDeg) |
| C | int OQAddSphericalAngleVariable(HOptQuestModel model, const char* name, double minThetaDeg, double maxThetaDeg, double minPhiDeg, double maxPhiDeg) |
| Python | bool OptQuestModel.add_spherical_angle_variable(str name, float min_theta_deg, float max_theta_deg, float min_phi_deg, float max_phi_deg) |
Description
Adds a spherical angle variable. Its value is a direction in three dimensions, given as an elevation and an azimuth in degrees. Use a spherical angle variable when the decision is a pointing direction, such as an antenna boresight or a sensor line of sight.
In every solution that the engine generates, the elevation is from minThetaDeg to maxThetaDeg, and the azimuth is on the arc from minPhiDeg to maxPhiDeg. The azimuth arc follows the same rules as the arc of an angle variable: a difference of 360 or more is the full circle, and an arc with minPhiDeg greater than maxPhiDeg crosses 0.
The engine reports the azimuth as its equivalent in [0, 360), which can differ from the range that you declare. For example, for an azimuth declared from -60 to 60, the engine reports 300 for -60. The engine reports the elevation as it is, within the declared range.
Notes
- Variable names:
<name>@theta: the elevation in degrees, from -90 (straight down) through 0 (the horizon) to 90 (straight up).<name>@phi: the azimuth in degrees, where 0 is north and 90 is east.
- Elevation convention: -90° is straight down, 0° is the horizon and +90° is straight up. This is not the physics colatitude in [0, 180].
- The elevation bounds must lie within [-90°, +90°],
minThetaDegmust not exceedmaxThetaDeg, and neither may be NaN. Otherwise the call fails in the usual way for the language. The azimuth bounds are unrestricted.
Add Region Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddRegionVariable(String name, double[][] polygon) throws COptQuestException |
| C# | bool OptQuestModel.AddRegionVariable(string name, double[][] polygon) |
| C++ | bool OptQuestModel::AddRegionVariable(const char* name, const double** polygon, int nVertices, int coordsPerVertex) |
| C | int OQAddRegionVariable(HOptQuestModel model, const char* name, const double** polygon, int nVertices, int coordsPerVertex) |
| Python | bool OptQuestModel.add_region_variable(str name, list[list[float]] polygon) |
Description
Adds a region variable. Its value is a point (x, y) in a plane polygon. Use a region variable when the decision is a location inside a region, such as a site inside a property boundary.
In every solution that the engine generates, the point is inside the polygon or on its boundary. The polygon can be non-convex. A point is inside by the even-odd rule, so a polygon whose edges cross each other is also accepted.
Give the vertices in either order, clockwise or counterclockwise. You do not need to repeat the first vertex at the end.
Notes
- Variable names:
<name>@xand<name>@y, the coordinates of the point, in the units of the polygon. polygonis a list of[x, y]vertices; there must be at least 3.- In C and C++,
polygonis a pointer to an array ofnVerticespointers, each to a vertex ofcoordsPerVertexdoubles (2 for this variable).
Add Spherical Region Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSphericalRegionVariable(String name, double[][] polygon) throws COptQuestException |
| C# | bool OptQuestModel.AddSphericalRegionVariable(string name, double[][] polygon) |
| C++ | bool OptQuestModel::AddSphericalRegionVariable(const char* name, const double** polygon, int nVertices, int coordsPerVertex) |
| C | int OQAddSphericalRegionVariable(HOptQuestModel model, const char* name, const double** polygon, int nVertices, int coordsPerVertex) |
| Python | bool OptQuestModel.add_spherical_region_variable(str name, list[list[float]] polygon) |
Description
Adds a spherical region variable. Its value is a point (latitude, longitude) in a polygon on the surface of the Earth. Use a spherical region variable when the decision is a location inside a geographic region, such as a sensor site inside a border.
In every solution that the engine generates, the point is inside the region or on its boundary. The edges of the polygon are great-circle arcs, not lines of constant latitude.
List the vertices clockwise, as on a map with north up: the region is on your right as you walk from each vertex to the next. This is the Esri rule for the outer ring of a polygon. The same vertices in counterclockwise order give the rest of the Earth. A region can enclose a pole, span more than 180 degrees of longitude, or be larger than a hemisphere. For a region around the North Pole, list the vertices from east to west. You do not need to repeat the first vertex at the end. The boundary must not cross itself.
Notes
- Variable names:
<name>@theta: the latitude of the point, in degrees.<name>@phi: the longitude of the point, in degrees, from -180 to 180.
polygonis a list of[latitude, longitude]vertices in degrees, latitude first; there must be at least 3 different vertices. A vertex that repeats the one before it is ignored.- The model refuses a latitude outside [-90, 90], a coordinate that is not a finite number, fewer than 3 different vertices, two consecutive vertices that are antipodal (the edge between them is not defined), and a boundary that doubles back on itself or encloses no area. In Java the Add call throws
COptQuestException. In the other languages the model fails when it initializes. - In C and C++,
polygonis a pointer to an array ofnVerticespointers, each to a vertex ofcoordsPerVertexdoubles (2 for this variable).
Special Purpose: Smooth
Use a smooth variable when your decision is a long list or a large table of numbers, and neighboring values are expected to be close. Examples are an hourly pumping schedule, a temperature profile along a reactor, and a table of set points by month and zone. For each smooth type you set one small number: a number of knots, a number of cosine terms or a rank. In every solution that the engine generates, the values have a shape that this number allows, and every element is from min to max.
| Your values | Type | The number that you set |
|---|---|---|
| A profile that changes smoothly along its length | Spline Vector (the curve passes through its knots) or B-spline Vector (the curve does not pass through its knots) | numKnots: fewer knots give a smoother curve |
| A profile made of gradual waves, such as a daily cycle | Fourier Vector | numFreq: fewer cosine terms give a smoother vector |
| A table that changes smoothly in both directions | Spline Matrix, B-spline Matrix or Fourier Matrix | the number of knots or cosine terms in each direction |
| A table whose rows follow a few common patterns | Low-Rank Matrix | rank: the number of row patterns |
| A long series that repeats, such as hourly values over many days | Time-Series Vector | rank: the number of repeating patterns |
| A known profile or table that you want to change | the Correction type of any of the above | as above |
| A correction that you build one pattern at a time, over several runs | Incremental Low-Rank Correction Matrix or Incremental Time-Series Correction Vector | rank: the number of the step, from 1 |
Each type has a correction variant. It takes a baseline, initial, and adds a smooth correction to it, so the values are initial + correction. Use a correction variant to keep a known profile or table and optimize only a smooth adjustment to it. The engine first moves each entry of initial into [min, max].
Variable names follow the container convention: <name>@1 … <name>@length for a vector, <name>@<row>,<col> for a matrix, and <name>@1 … <name>@(longScale × shortScale) for a time-series vector.
Add Low-Rank Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddLowRankMatrixVariable(String name, int rows, int cols, int rank, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddLowRankMatrixVariable(string name, int rows, int cols, int rank, double min, double max) |
| C++ | bool OptQuestModel::AddLowRankMatrixVariable(const char* name, int rows, int cols, int rank, double min, double max) |
| C | int OQAddLowRankMatrixVariable(HOptQuestModel model, const char* name, int rows, int cols, int rank, double min, double max) |
| Python | bool OptQuestModel.add_lowrank_matrix_variable(str name, int rows, int cols, int rank, float min_val, float max_val) |
Description
Adds a low-rank matrix variable. Its value is a rows by cols matrix that is a constant matrix plus a correction of low rank. Use a low-rank matrix variable when the decision is a large table that you can describe with a few row and column patterns.
In every solution that the engine generates, every entry is from min to max, and the matrix is the constant matrix (min + max) / 2 plus a correction of rank at most rank. So the matrix itself can have rank rank + 1.
The value of rank is the number of row patterns that the engine can combine. With rank 1, each row of the matrix is the middle value (min + max) / 2 plus one row pattern, multiplied by an amount that can differ from row to row. Each extra unit of rank adds one more row pattern. With rank 0, every entry is the middle value.
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. rank: largest rank of the correction. A value greater than the number of rows or columns is reduced to it, and a value of 0 or less gives a constant matrix.
Add Low-Rank Correction Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddLowRankCorrectionMatrixVariable(String name, double[][] initial, int rank, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddLowRankCorrectionMatrixVariable(string name, double[][] initial, int rank, double min, double max) |
| C++ | bool OptQuestModel::AddLowRankCorrectionMatrixVariable(const char* name, const double** initial, int rows, int cols, int rank, double min, double max) |
| C | int OQAddLowRankCorrectionMatrixVariable(HOptQuestModel model, const char* name, const double** initial, int rows, int cols, int rank, double min, double max) |
| Python | bool OptQuestModel.add_lowrank_correction_matrix_variable(str name, list[list[float]] initial, int rank, float min_val, float max_val) |
Description
Adds a low-rank correction matrix variable. Its value is a baseline matrix, initial, plus a correction of low rank. Use a low-rank correction matrix variable to keep a known table and change it with a few row and column patterns.
In every solution that the engine generates, every entry is from min to max, and the matrix is initial plus a correction of rank at most rank, except where an entry of initial is on min or max and the correction points past that bound: there the engine keeps the entry on the bound, and the correction can have a higher rank. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. initial: the baseline matrix; its shape sets the number of rows and columns.rank: largest rank of the correction. A value greater than the number of rows or columns is reduced to it, and a value of 0 or less gives a constant matrix.- In C and C++,
initialis a pointer to an array ofrowspointers, each to a row ofcolsdoubles.
Add Incremental Low-Rank Correction Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddIncrementalLowRankCorrectionMatrixVariable(String name, double[][] initial, int rank, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddIncrementalLowRankCorrectionMatrixVariable(string name, double[][] initial, int rank, double min, double max) |
| C++ | bool OptQuestModel::AddIncrementalLowRankCorrectionMatrixVariable(const char* name, const double** initial, int rows, int cols, int rank, double min, double max) |
| C | int OQAddIncrementalLowRankCorrectionMatrixVariable(HOptQuestModel model, const char* name, const double** initial, int rows, int cols, int rank, double min, double max) |
| Python | bool OptQuestModel.add_incremental_lowrank_correction_matrix_variable(str name, list[list[float]] initial, int rank, float min_val, float max_val) |
Description
Adds an incremental low-rank correction matrix variable. Its value is a baseline matrix, initial, plus a correction of rank 1. Use this variable to build a correction one rank at a time. Run an optimization, pass its best value as initial of the next variable of this type, and repeat. Each variable adds a correction of rank 1 and does not keep the corrections of earlier variables.
In every solution that the engine generates, every entry is from min to max, and the matrix is initial plus a correction of rank at most 1, except where an entry of initial is on min or max and the correction points past that bound: there the engine keeps the entry on the bound, and the correction can have a higher rank. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. initial: the baseline matrix; its shape sets the number of rows and columns.rank: the number of this step in the sequence, from 1. It does not change the values. A value less than 1 is refused. In Java the call throws an exception. In the other languages the call succeeds, and the model fails when it initializes, with the error “Invalid rank for an incremental variable: rank=N. The rank must be at least 1.”- In C and C++,
initialis a pointer to an array ofrowspointers, each to a row ofcolsdoubles.
Add Time-Series Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddTimeSeriesVectorVariable(String name, int longScale, int shortScale, int rank, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddTimeSeriesVectorVariable(string name, int longScale, int shortScale, int rank, double min, double max) |
| C++ | bool OptQuestModel::AddTimeSeriesVectorVariable(const char* name, int longScale, int shortScale, int rank, double min, double max) |
| C | int OQAddTimeSeriesVectorVariable(HOptQuestModel model, const char* name, int longScale, int shortScale, int rank, double min, double max) |
| Python | bool OptQuestModel.add_timeseries_vector_variable(str name, int long_scale, int short_scale, int rank, float min_val, float max_val) |
Description
Adds a time-series vector variable. Its value is a vector of longScale × shortScale values. The engine arranges the values row by row as a longScale by shortScale matrix, and the matrix is a constant plus a correction of low rank. Use a time-series vector variable when the decision is a long vector with a repeating pattern, such as hourly values over many days.
In every solution that the engine generates, every value is from min to max, and the matrix is the constant matrix (min + max) / 2 plus a correction of rank at most rank.
The value of rank is the number of patterns that the engine can combine. With days as rows, hours as columns and rank 1, each day is the middle value (min + max) / 2 plus one pattern over the hours, multiplied by an amount that can differ from day to day. So every day has the same shape, and the size of the change can differ from day to day. Each extra unit of rank adds one more pattern. With rank 0, every value is the middle value.
Notes
- Variable names:
<name>@1to<name>@n, where n islongScale×shortScale. The engine numbers the entries row by row. The entry in row r and column c of the matrix, both counted from 1, is<name>@k, where k = (r - 1) ×shortScale+ c. For example, withshortScale= 24, hour 5 of day 3 is<name>@53. longScale: number of rows of the matrix, for example the number of days; must be at least 1.shortScale: number of columns of the matrix, for example the number of hours in a day; must be at least 1.rank: largest rank of the correction. A value greater than the number of rows or columns is reduced to it, and a value of 0 or less gives a constant matrix.
Add Time-Series Correction Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddTimeSeriesCorrectionVectorVariable(String name, double[] initial, int longScale, int shortScale, int rank, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddTimeSeriesCorrectionVectorVariable(string name, double[] initial, int longScale, int shortScale, int rank, double min, double max) |
| C++ | bool OptQuestModel::AddTimeSeriesCorrectionVectorVariable(const char* name, const double* initial, int longScale, int shortScale, int rank, double min, double max) |
| C | int OQAddTimeSeriesCorrectionVectorVariable(HOptQuestModel model, const char* name, const double* initial, int longScale, int shortScale, int rank, double min, double max) |
| Python | bool OptQuestModel.add_timeseries_correction_vector_variable(str name, list[float] initial, int long_scale, int short_scale, int rank, float min_val, float max_val) |
Description
Adds a time-series correction vector variable. Its value is a baseline vector, initial, plus a correction. The engine arranges the values row by row as a longScale by shortScale matrix, and the correction to that matrix has low rank. Use a time-series correction vector variable to keep a known profile and change it with a few repeating patterns.
In every solution that the engine generates, every value is from min to max, and the matrix is initial plus a correction of rank at most rank, except where an entry of initial is on min or max and the correction points past that bound: there the engine keeps the entry on the bound, and the correction can have a higher rank. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@1to<name>@n, where n islongScale×shortScale. The engine numbers the entries row by row. The entry in row r and column c of the matrix, both counted from 1, is<name>@k, where k = (r - 1) ×shortScale+ c. For example, withshortScale= 24, hour 5 of day 3 is<name>@53. initial: the baseline vector; it must havelongScale×shortScalevalues.longScale: number of rows of the matrix, for example the number of days; must be at least 1.shortScale: number of columns of the matrix, for example the number of hours in a day; must be at least 1.rank: largest rank of the correction. A value greater than the number of rows or columns is reduced to it, and a value of 0 or less gives a constant matrix.- In C and C++,
initialis a pointer to an array oflongScale × shortScaledoubles in row-major order.
Add Incremental Time-Series Correction Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddIncrementalTimeSeriesCorrectionVectorVariable(String name, double[] initial, int longScale, int shortScale, int rank, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddIncrementalTimeSeriesCorrectionVectorVariable(string name, double[] initial, int longScale, int shortScale, int rank, double min, double max) |
| C++ | bool OptQuestModel::AddIncrementalTimeSeriesCorrectionVectorVariable(const char* name, const double* initial, int longScale, int shortScale, int rank, double min, double max) |
| C | int OQAddIncrementalTimeSeriesCorrectionVectorVariable(HOptQuestModel model, const char* name, const double* initial, int longScale, int shortScale, int rank, double min, double max) |
| Python | bool OptQuestModel.add_incremental_timeseries_correction_vector_variable(str name, list[float] initial, int long_scale, int short_scale, int rank, float min_val, float max_val) |
Description
Adds an incremental time-series correction vector variable. Its value is a baseline vector, initial, plus a correction. The engine arranges the values row by row as a longScale by shortScale matrix, and the correction to that matrix has rank 1. Use this variable to build a correction one rank at a time. Run an optimization, pass its best value as initial of the next variable of this type, and repeat. Each variable adds a correction of rank 1 and does not keep the corrections of earlier variables.
In every solution that the engine generates, every value is from min to max, and the matrix is initial plus a correction of rank at most 1, except where an entry of initial is on min or max and the correction points past that bound: there the engine keeps the entry on the bound, and the correction can have a higher rank. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@1to<name>@n, where n islongScale×shortScale. The engine numbers the entries row by row. The entry in row r and column c of the matrix, both counted from 1, is<name>@k, where k = (r - 1) ×shortScale+ c. For example, withshortScale= 24, hour 5 of day 3 is<name>@53. initial: the baseline vector; it must havelongScale×shortScalevalues.longScale: number of rows of the matrix, for example the number of days; must be at least 1.shortScale: number of columns of the matrix, for example the number of hours in a day; must be at least 1.rank: the number of this step in the sequence, from 1. It does not change the values. A value less than 1 is refused. In Java the call throws an exception. In the other languages the call succeeds, and the model fails when it initializes, with the error “Invalid rank for an incremental variable: rank=N. The rank must be at least 1.”- In C and C++,
initialis a pointer to an array oflongScale × shortScaledoubles in row-major order.
Add BSpline Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBSplineVectorVariable(String name, int length, int numKnots, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddBSplineVectorVariable(string name, int length, int numKnots, double min, double max) |
| C++ | bool OptQuestModel::AddBSplineVectorVariable(const char* name, int length, int numKnots, double min, double max) |
| C | int OQAddBSplineVectorVariable(HOptQuestModel model, const char* name, int length, int numKnots, double min, double max) |
| Python | bool OptQuestModel.add_bspline_vector_variable(str name, int length, int num_knots, float min_val, float max_val) |
Description
Adds a B-spline vector variable. Its value is a vector of length values on a smooth curve defined by numKnots knots. Use a B-spline vector variable when the decision is a long profile that changes smoothly, such as a setpoint schedule.
The curve is a uniform cubic B-spline. It is smooth, and it does not pass through its knots: each value is a weighted average of the nearby knot values. The knots are at evenly spaced elements, with the first and last knots at the two ends.
In every solution that the engine generates, every element is from min to max.
Notes
- Variable names:
<name>@1to<name>@length, one for each element. numKnots: number of knots; fewer knots give a smoother curve. A value less than 2 is used as 2, and a value greater than the number of elements is used as that number.
Add Spline Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSplineVectorVariable(String name, int length, int numKnots, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddSplineVectorVariable(string name, int length, int numKnots, double min, double max) |
| C++ | bool OptQuestModel::AddSplineVectorVariable(const char* name, int length, int numKnots, double min, double max) |
| C | int OQAddSplineVectorVariable(HOptQuestModel model, const char* name, int length, int numKnots, double min, double max) |
| Python | bool OptQuestModel.add_spline_vector_variable(str name, int length, int num_knots, float min_val, float max_val) |
Description
Adds a spline vector variable. Its value is a vector of length values on a smooth curve through numKnots knots. Use a spline vector variable when the decision is a long profile that changes smoothly, such as a setpoint schedule.
The curve is a centripetal Catmull-Rom spline. It is smooth, and it passes through its knots. The knots are at evenly spaced elements, with the first and last knots at the two ends.
In every solution that the engine generates, every element is from min to max.
Notes
- Variable names:
<name>@1to<name>@length, one for each element. numKnots: number of knots; fewer knots give a smoother curve. A value less than 2 is used as 2, and a value greater than the number of elements is used as that number.
Add BSpline Correction Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBSplineCorrectionVectorVariable(String name, double[] initial, int numKnots, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddBSplineCorrectionVectorVariable(string name, double[] initial, int numKnots, double min, double max) |
| C++ | bool OptQuestModel::AddBSplineCorrectionVectorVariable(const char* name, const double* initial, int n, int numKnots, double min, double max) |
| C | int OQAddBSplineCorrectionVectorVariable(HOptQuestModel model, const char* name, const double* initial, int n, int numKnots, double min, double max) |
| Python | bool OptQuestModel.add_bspline_correction_vector_variable(str name, list[float] initial, int num_knots, float min_val, float max_val) |
Description
Adds a B-spline correction vector variable. Its value is a baseline vector, initial, plus a correction on a smooth curve defined by numKnots knots. Use a B-spline correction vector variable to keep a known profile and change it smoothly.
The curve is a uniform cubic B-spline. It is smooth, and it does not pass through its knots: each value is a weighted average of the nearby knot values. The knots are at evenly spaced elements, with the first and last knots at the two ends.
In every solution that the engine generates, every element is from min to max. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@1to<name>@length, one for each element. The number of elements is the length ofinitial. initial: the baseline vector; its length sets the number of elements.numKnots: number of knots; fewer knots give a smoother curve. A value less than 2 is used as 2, and a value greater than the number of elements is used as that number.- In C and C++,
initialis a pointer to an array ofndoubles.
Add Spline Correction Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSplineCorrectionVectorVariable(String name, double[] initial, int numKnots, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddSplineCorrectionVectorVariable(string name, double[] initial, int numKnots, double min, double max) |
| C++ | bool OptQuestModel::AddSplineCorrectionVectorVariable(const char* name, const double* initial, int n, int numKnots, double min, double max) |
| C | int OQAddSplineCorrectionVectorVariable(HOptQuestModel model, const char* name, const double* initial, int n, int numKnots, double min, double max) |
| Python | bool OptQuestModel.add_spline_correction_vector_variable(str name, list[float] initial, int num_knots, float min_val, float max_val) |
Description
Adds a spline correction vector variable. Its value is a baseline vector, initial, plus a correction on a smooth curve through numKnots knots. Use a spline correction vector variable to keep a known profile and change it smoothly.
The curve is a centripetal Catmull-Rom spline. It is smooth, and it passes through its knots. The knots are at evenly spaced elements, with the first and last knots at the two ends.
In every solution that the engine generates, every element is from min to max. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@1to<name>@length, one for each element. The number of elements is the length ofinitial. initial: the baseline vector; its length sets the number of elements.numKnots: number of knots; fewer knots give a smoother curve. A value less than 2 is used as 2, and a value greater than the number of elements is used as that number.- In C and C++,
initialis a pointer to an array ofndoubles.
Add BSpline Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBSplineMatrixVariable(String name, int rows, int cols, int knotRows, int knotCols, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddBSplineMatrixVariable(string name, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| C++ | bool OptQuestModel::AddBSplineMatrixVariable(const char* name, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| C | int OQAddBSplineMatrixVariable(HOptQuestModel model, const char* name, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| Python | bool OptQuestModel.add_bspline_matrix_variable(str name, int rows, int cols, int knot_rows, int knot_cols, float min_val, float max_val) |
Description
Adds a B-spline matrix variable. Its value is a rows by cols matrix on a smooth surface defined by a grid of knots. Use a B-spline matrix variable when the decision is a large table that changes smoothly in both directions.
The surface is a uniform cubic B-spline. It is smooth, and it does not pass through its knots: each value is a weighted average of the nearby knot values. The knots form a knotRows by knotCols grid at evenly spaced rows and columns, with knots at all four edges.
In every solution that the engine generates, every entry is from min to max.
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. knotRows: number of knot rows; fewer give a smoother surface down the columns. A value less than 2 is used as 2, and a value greater than the number of rows is used as that number.knotCols: number of knot columns; fewer give a smoother surface along the rows. A value less than 2 is used as 2, and a value greater than the number of columns is used as that number.
Add Spline Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSplineMatrixVariable(String name, int rows, int cols, int knotRows, int knotCols, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddSplineMatrixVariable(string name, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| C++ | bool OptQuestModel::AddSplineMatrixVariable(const char* name, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| C | int OQAddSplineMatrixVariable(HOptQuestModel model, const char* name, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| Python | bool OptQuestModel.add_spline_matrix_variable(str name, int rows, int cols, int knot_rows, int knot_cols, float min_val, float max_val) |
Description
Adds a spline matrix variable. Its value is a rows by cols matrix on a smooth surface through a grid of knots. Use a spline matrix variable when the decision is a large table that changes smoothly in both directions.
The surface is a centripetal Catmull-Rom spline. It is smooth, and it passes through its knots. The knots form a knotRows by knotCols grid at evenly spaced rows and columns, with knots at all four edges.
In every solution that the engine generates, every entry is from min to max.
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. knotRows: number of knot rows; fewer give a smoother surface down the columns. A value less than 2 is used as 2, and a value greater than the number of rows is used as that number.knotCols: number of knot columns; fewer give a smoother surface along the rows. A value less than 2 is used as 2, and a value greater than the number of columns is used as that number.
Add BSpline Correction Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBSplineCorrectionMatrixVariable(String name, double[][] initial, int knotRows, int knotCols, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddBSplineCorrectionMatrixVariable(string name, double[][] initial, int knotRows, int knotCols, double min, double max) |
| C++ | bool OptQuestModel::AddBSplineCorrectionMatrixVariable(const char* name, const double** initial, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| C | int OQAddBSplineCorrectionMatrixVariable(HOptQuestModel model, const char* name, const double** initial, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| Python | bool OptQuestModel.add_bspline_correction_matrix_variable(str name, list[list[float]] initial, int knot_rows, int knot_cols, float min_val, float max_val) |
Description
Adds a B-spline correction matrix variable. Its value is a baseline matrix, initial, plus a correction on a smooth surface defined by a grid of knots. Use a B-spline correction matrix variable to keep a known table and change it smoothly.
The surface is a uniform cubic B-spline. It is smooth, and it does not pass through its knots: each value is a weighted average of the nearby knot values. The knots form a knotRows by knotCols grid at evenly spaced rows and columns, with knots at all four edges.
In every solution that the engine generates, every entry is from min to max. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. initial: the baseline matrix; its shape sets the number of rows and columns.knotRows: number of knot rows; fewer give a smoother surface down the columns. A value less than 2 is used as 2, and a value greater than the number of rows is used as that number.knotCols: number of knot columns; fewer give a smoother surface along the rows. A value less than 2 is used as 2, and a value greater than the number of columns is used as that number.- In C and C++,
initialis a pointer to an array ofrowspointers, each to a row ofcolsdoubles.
Add Spline Correction Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSplineCorrectionMatrixVariable(String name, double[][] initial, int knotRows, int knotCols, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddSplineCorrectionMatrixVariable(string name, double[][] initial, int knotRows, int knotCols, double min, double max) |
| C++ | bool OptQuestModel::AddSplineCorrectionMatrixVariable(const char* name, const double** initial, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| C | int OQAddSplineCorrectionMatrixVariable(HOptQuestModel model, const char* name, const double** initial, int rows, int cols, int knotRows, int knotCols, double min, double max) |
| Python | bool OptQuestModel.add_spline_correction_matrix_variable(str name, list[list[float]] initial, int knot_rows, int knot_cols, float min_val, float max_val) |
Description
Adds a spline correction matrix variable. Its value is a baseline matrix, initial, plus a correction on a smooth surface through a grid of knots. Use a spline correction matrix variable to keep a known table and change it smoothly.
The surface is a centripetal Catmull-Rom spline. It is smooth, and it passes through its knots. The knots form a knotRows by knotCols grid at evenly spaced rows and columns, with knots at all four edges.
In every solution that the engine generates, every entry is from min to max. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. initial: the baseline matrix; its shape sets the number of rows and columns.knotRows: number of knot rows; fewer give a smoother surface down the columns. A value less than 2 is used as 2, and a value greater than the number of rows is used as that number.knotCols: number of knot columns; fewer give a smoother surface along the rows. A value less than 2 is used as 2, and a value greater than the number of columns is used as that number.- In C and C++,
initialis a pointer to an array ofrowspointers, each to a row ofcolsdoubles.
Add Fourier Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddFourierVectorVariable(String name, int length, int numFreq, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddFourierVectorVariable(string name, int length, int numFreq, double min, double max) |
| C++ | bool OptQuestModel::AddFourierVectorVariable(const char* name, int length, int numFreq, double min, double max) |
| C | int OQAddFourierVectorVariable(HOptQuestModel model, const char* name, int length, int numFreq, double min, double max) |
| Python | bool OptQuestModel.add_fourier_vector_variable(str name, int length, int num_freq, float min_val, float max_val) |
Description
Adds a Fourier vector variable. Its value is a vector of length values that is a sum of the numFreq lowest-frequency cosine terms. Use a Fourier vector variable when the decision is a long profile that varies smoothly, such as a daily cycle.
The first term is a constant. The second term is half of a cosine wave across the whole vector. Each next term adds one more half wave, so the later terms add finer detail. With one term, every element has the same value. For element i, counted from 1, term k is cos(π k (i - 0.5) / length), where k counts from 0.
In every solution that the engine generates, every element is from min to max.
Notes
- Variable names:
<name>@1to<name>@length, one for each element. numFreq: number of cosine terms, including the constant term; fewer give a smoother vector. A value less than 1 is used as 1, and a value greater than the number of elements is used as that number.
Add Fourier Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddFourierMatrixVariable(String name, int rows, int cols, int freqRows, int freqCols, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddFourierMatrixVariable(string name, int rows, int cols, int freqRows, int freqCols, double min, double max) |
| C++ | bool OptQuestModel::AddFourierMatrixVariable(const char* name, int rows, int cols, int freqRows, int freqCols, double min, double max) |
| C | int OQAddFourierMatrixVariable(HOptQuestModel model, const char* name, int rows, int cols, int freqRows, int freqCols, double min, double max) |
| Python | bool OptQuestModel.add_fourier_matrix_variable(str name, int rows, int cols, int freq_rows, int freq_cols, float min_val, float max_val) |
Description
Adds a Fourier matrix variable. Its value is a rows by cols matrix that is a sum of the lowest-frequency cosine terms: freqRows terms down the columns and freqCols terms along the rows. Use a Fourier matrix variable when the decision is a large table that varies smoothly in both directions.
The terms are products of a cosine down the columns and a cosine along the rows, like the terms of the vector type. With one term down the columns, every row is the same. With one term along the rows, every column is the same.
In every solution that the engine generates, every entry is from min to max.
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. freqRows: number of cosine terms down each column; fewer make the rows more alike. A value less than 1 is used as 1, and a value greater than the number of rows is used as that number.freqCols: number of cosine terms along each row; fewer make the columns more alike. A value less than 1 is used as 1, and a value greater than the number of columns is used as that number.
Add Fourier Correction Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddFourierCorrectionVectorVariable(String name, double[] initial, int numFreq, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddFourierCorrectionVectorVariable(string name, double[] initial, int numFreq, double min, double max) |
| C++ | bool OptQuestModel::AddFourierCorrectionVectorVariable(const char* name, const double* initial, int n, int numFreq, double min, double max) |
| C | int OQAddFourierCorrectionVectorVariable(HOptQuestModel model, const char* name, const double* initial, int n, int numFreq, double min, double max) |
| Python | bool OptQuestModel.add_fourier_correction_vector_variable(str name, list[float] initial, int num_freq, float min_val, float max_val) |
Description
Adds a Fourier correction vector variable. Its value is a baseline vector, initial, plus a correction that is a sum of the numFreq lowest-frequency cosine terms. Use a Fourier correction vector variable to keep a known profile and change it smoothly.
The first term is a constant. The second term is half of a cosine wave across the whole vector. Each next term adds one more half wave, so the later terms add finer detail. With one term, the correction has the same value at every element. For element i, counted from 1, term k is cos(π k (i - 0.5) / n), where k counts from 0 and n is the length of initial.
In every solution that the engine generates, every element is from min to max. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@1to<name>@length, one for each element. The number of elements is the length ofinitial. initial: the baseline vector; its length sets the number of elements.numFreq: number of cosine terms, including the constant term; fewer give a smoother vector. A value less than 1 is used as 1, and a value greater than the number of elements is used as that number.- In C and C++,
initialis a pointer to an array ofndoubles.
Add Fourier Correction Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddFourierCorrectionMatrixVariable(String name, double[][] initial, int freqRows, int freqCols, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddFourierCorrectionMatrixVariable(string name, double[][] initial, int freqRows, int freqCols, double min, double max) |
| C++ | bool OptQuestModel::AddFourierCorrectionMatrixVariable(const char* name, const double** initial, int rows, int cols, int freqRows, int freqCols, double min, double max) |
| C | int OQAddFourierCorrectionMatrixVariable(HOptQuestModel model, const char* name, const double** initial, int rows, int cols, int freqRows, int freqCols, double min, double max) |
| Python | bool OptQuestModel.add_fourier_correction_matrix_variable(str name, list[list[float]] initial, int freq_rows, int freq_cols, float min_val, float max_val) |
Description
Adds a Fourier correction matrix variable. Its value is a baseline matrix, initial, plus a correction that is a sum of the lowest-frequency cosine terms: freqRows terms down the columns and freqCols terms along the rows. Use a Fourier correction matrix variable to keep a known table and change it smoothly.
The terms are products of a cosine down the columns and a cosine along the rows, like the terms of the vector type. With one term down the columns, every row of the correction is the same. With one term along the rows, every column of the correction is the same.
In every solution that the engine generates, every entry is from min to max. The engine first moves each entry of initial into [min, max].
Notes
- Variable names:
<name>@<row>,<col>for each entry, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2]. initial: the baseline matrix; its shape sets the number of rows and columns.freqRows: number of cosine terms down each column; fewer make the rows more alike. A value less than 1 is used as 1, and a value greater than the number of rows is used as that number.freqCols: number of cosine terms along each row; fewer make the columns more alike. A value less than 1 is used as 1, and a value greater than the number of columns is used as that number.- In C and C++,
initialis a pointer to an array ofrowspointers, each to a row ofcolsdoubles.
Random
Each function in this family adds a variable named name whose value is a random draw. At the start of every replication the engine draws a new value from the named distribution. Within one replication the value is fixed; between replications it changes. Without SetReplications, each trial solution has one replication, so it gets one draw, and its result depends on that one draw. To compare trial solutions by the combined result of several draws, call SetReplications with more than one replication (see § Stochastic Simulation Optimization). The evaluator reads it like any other input, and GetInputNames lists it. The distributions follow the scipy.stats definitions given in § Reference › Probability Distributions.
Add Beta Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddBetaRandomVariable(String name, double alpha, double beta) throws COptQuestException |
| C# | bool OptQuestModel.AddBetaRandomVariable(string name, double alpha, double beta) |
| C++ | bool OptQuestModel::AddBetaRandomVariable(const char* name, double alpha, double beta) |
| C | int OQAddBetaRandomVariable(HOptQuestModel model, const char* name, double alpha, double beta) |
| Python | bool OptQuestModel.add_beta_random_variable(str name, float alpha, float beta) |
Description
Adds a Beta-distributed variable with the shape parameters alpha and beta, both greater than 0.
Add Cauchy Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddCauchyRandomVariable(String name, double location, double scale) throws COptQuestException |
| C# | bool OptQuestModel.AddCauchyRandomVariable(string name, double location, double scale) |
| C++ | bool OptQuestModel::AddCauchyRandomVariable(const char* name, double location, double scale) |
| C | int OQAddCauchyRandomVariable(HOptQuestModel model, const char* name, double location, double scale) |
| Python | bool OptQuestModel.add_cauchy_random_variable(str name, float location, float scale) |
Description
Adds a Cauchy-distributed variable with the location parameter location and the scale parameter scale, which must be greater than 0.
Add Chi-Square Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddChiSquareRandomVariable(String name, int df) throws COptQuestException |
| C# | bool OptQuestModel.AddChiSquareRandomVariable(string name, int df) |
| C++ | bool OptQuestModel::AddChiSquareRandomVariable(const char* name, int df) |
| C | int OQAddChiSquareRandomVariable(HOptQuestModel model, const char* name, int df) |
| Python | bool OptQuestModel.add_chi_square_random_variable(str name, int df) |
Description
Adds a Chi-square-distributed variable with df degrees of freedom, a positive integer.
Add Exponential Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddExponentialRandomVariable(String name, double scale) throws COptQuestException |
| C# | bool OptQuestModel.AddExponentialRandomVariable(string name, double scale) |
| C++ | bool OptQuestModel::AddExponentialRandomVariable(const char* name, double scale) |
| C | int OQAddExponentialRandomVariable(HOptQuestModel model, const char* name, double scale) |
| Python | bool OptQuestModel.add_exponential_random_variable(str name, float scale) |
Description
Adds an exponentially distributed variable with the scale parameter scale, which must be greater than 0.
Add Gamma Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddGammaRandomVariable(String name, double shape, double scale) throws COptQuestException |
| C# | bool OptQuestModel.AddGammaRandomVariable(string name, double shape, double scale) |
| C++ | bool OptQuestModel::AddGammaRandomVariable(const char* name, double shape, double scale) |
| C | int OQAddGammaRandomVariable(HOptQuestModel model, const char* name, double shape, double scale) |
| Python | bool OptQuestModel.add_gamma_random_variable(str name, float shape, float scale) |
Description
Adds a Gamma-distributed variable with the shape parameter shape and the scale parameter scale, both greater than 0.
Add Log-Normal Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddLogNormalRandomVariable(String name, double shape, double scale) throws COptQuestException |
| C# | bool OptQuestModel.AddLogNormalRandomVariable(string name, double shape, double scale) |
| C++ | bool OptQuestModel::AddLogNormalRandomVariable(const char* name, double shape, double scale) |
| C | int OQAddLogNormalRandomVariable(HOptQuestModel model, const char* name, double shape, double scale) |
| Python | bool OptQuestModel.add_log_normal_random_variable(str name, float shape, float scale) |
Description
Adds a log-normally distributed variable with the shape parameter shape and the scale parameter scale, both greater than 0.
Add Normal Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddNormalRandomVariable(String name, double mean, double sigma) throws COptQuestException |
| C# | bool OptQuestModel.AddNormalRandomVariable(string name, double mean, double sigma) |
| C++ | bool OptQuestModel::AddNormalRandomVariable(const char* name, double mean, double sigma) |
| C | int OQAddNormalRandomVariable(HOptQuestModel model, const char* name, double mean, double sigma) |
| Python | bool OptQuestModel.add_normal_random_variable(str name, float mean, float sigma) |
Description
Adds a normally distributed variable with the mean mean and the standard deviation sigma, which must be greater than 0.
Add Pareto Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddParetoRandomVariable(String name, double gamma, double loc, double scale) throws COptQuestException |
| C# | bool OptQuestModel.AddParetoRandomVariable(string name, double gamma, double loc, double scale) |
| C++ | bool OptQuestModel::AddParetoRandomVariable(const char* name, double gamma, double loc, double scale) |
| C | int OQAddParetoRandomVariable(HOptQuestModel model, const char* name, double gamma, double loc, double scale) |
| Python | bool OptQuestModel.add_pareto_random_variable(str name, float gamma, float loc, float scale) |
Description
Adds a Pareto-distributed variable with the shape parameter gamma (greater than 0), the location parameter loc and the scale parameter scale (greater than 0). The smallest possible value is loc + scale. SetSampleRDSPareto uses the same three parameters.
Add Poisson Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddPoissonRandomVariable(String name, double lambda) throws COptQuestException |
| C# | bool OptQuestModel.AddPoissonRandomVariable(string name, double lambda) |
| C++ | bool OptQuestModel::AddPoissonRandomVariable(const char* name, double lambda) |
| C | int OQAddPoissonRandomVariable(HOptQuestModel model, const char* name, double lambda) |
| Python | bool OptQuestModel.add_poisson_random_variable(str name, float lambda_) |
Description
Adds a Poisson-distributed variable with the rate parameter lambda, which must be greater than 0. In Python the parameter is lambda_, because lambda is a keyword.
Add Power Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddPowerRandomVariable(String name, double rmin, double rmax, double power) throws COptQuestException |
| C# | bool OptQuestModel.AddPowerRandomVariable(string name, double rmin, double rmax, double power) |
| C++ | bool OptQuestModel::AddPowerRandomVariable(const char* name, double rmin, double rmax, double power) |
| C | int OQAddPowerRandomVariable(HOptQuestModel model, const char* name, double rmin, double rmax, double power) |
| Python | bool OptQuestModel.add_power_random_variable(str name, float rmin, float rmax, float power) |
Description
Adds a random variable whose value is from rmin to rmax. Use power to set where most of the values are. With power = 1, every value in the range is equally likely. With power = 2, the values are the distances from the center of points spread evenly over the area of a ring with the radii rmin and rmax. With power = 3, they are the distances from the center of points spread evenly over the volume of a spherical shell. With a larger power, more values are near rmax. With a power between 0 and 1, more values are near rmin.
The probability density is proportional to x^(power - 1):
pdf(x) = power * x^(power - 1) / (rmax^power - rmin^power) for rmin <= x <= rmax.
With power = 1, the density is the constant 1 / (rmax - rmin).
power must be greater than 0, rmin must be at least 0, and rmax must be greater than rmin. A power of 0 or less is rejected; the uniform case is power = 1.
Add Spherical Elevation Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSphericalElevationRandomVariable(String name, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddSphericalElevationRandomVariable(string name, double min, double max) |
| C++ | bool OptQuestModel::AddSphericalElevationRandomVariable(const char* name, double min, double max) |
| C | int OQAddSphericalElevationRandomVariable(HOptQuestModel model, const char* name, double min, double max) |
| Python | bool OptQuestModel.add_spherical_elevation_random_variable(str name, float min_val, float max_val) |
Description
Adds a spherical elevation variable, drawn uniformly by surface area from the band of the unit sphere between the elevations min and max in degrees. Uniform by surface area, rather than uniform by angle, means that values near the horizon are more likely than values near the poles. This matches a random pointing direction on a band of the sphere, as used in radar, antenna and surveillance models. The elevation convention is the engineering one: -90° is straight down, 0° is the horizon and +90° is straight up. The bounds must lie within [-90°, +90°].
Add Student T Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddStudentTRandomVariable(String name, int df) throws COptQuestException |
| C# | bool OptQuestModel.AddStudentTRandomVariable(string name, int df) |
| C++ | bool OptQuestModel::AddStudentTRandomVariable(const char* name, int df) |
| C | int OQAddStudentTRandomVariable(HOptQuestModel model, const char* name, int df) |
| Python | bool OptQuestModel.add_student_t_random_variable(str name, int df) |
Description
Adds a Student’s t-distributed variable with df degrees of freedom, a positive integer.
Add Uniform Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddUniformRandomVariable(String name, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddUniformRandomVariable(string name, double min, double max) |
| C++ | bool OptQuestModel::AddUniformRandomVariable(const char* name, double min, double max) |
| C | int OQAddUniformRandomVariable(HOptQuestModel model, const char* name, double min, double max) |
| Python | bool OptQuestModel.add_uniform_random_variable(str name, float min_val, float max_val) |
Description
Adds a uniformly distributed variable on [min, max], where max must be greater than min.
Add Weibull Random Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddWeibullRandomVariable(String name, double shape, double scale) throws COptQuestException |
| C# | bool OptQuestModel.AddWeibullRandomVariable(string name, double shape, double scale) |
| C++ | bool OptQuestModel::AddWeibullRandomVariable(const char* name, double shape, double scale) |
| C | int OQAddWeibullRandomVariable(HOptQuestModel model, const char* name, double shape, double scale) |
| Python | bool OptQuestModel.add_weibull_random_variable(str name, float shape, float scale) |
Description
Adds a Weibull-distributed variable with the shape parameter shape and the scale parameter scale, both greater than 0.
Output Variables
An output variable holds a value that the simulation writes for each trial solution. The engine never assigns it. The evaluator sets it with SetValue before the solution is submitted. In a solution from CreateSolution, and in the solution that a managed optimization gives to the evaluator, each output is NaN until the evaluator sets it, in each replication. If the evaluator does not set an output, each objective and constraint that uses it is NaN, and the solution is infeasible. The engine reports no error, and an infeasible solution with a NaN objective ranks after the other infeasible solutions. Set every output before you submit a solution, or reject the solution. A solution that you add with AddEvaluated keeps the output values that you give it. The output vector, matrix and ND functions create one output variable per element with the same element names as the container decision variables.
Add Output Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddOutputVariable(String name) throws COptQuestException |
| C# | bool OptQuestModel.AddOutputVariable(string name) |
| C++ | bool OptQuestModel::AddOutputVariable(const char* name) |
| C | int OQAddOutputVariable(HOptQuestModel model, const char* name) |
| Python | bool OptQuestModel.add_output_variable(str name) |
Description
Adds an output variable named name.
Set Output Statistic Parameters
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetOutputStatistic(String name, int statistic) throws COptQuestExceptionboolean OptQuestModel.SetOutputStatistic(String name, int statistic, double statisticValue) throws COptQuestException |
| C# | bool OptQuestModel.SetOutputStatistic(string name, int statistic)bool OptQuestModel.SetOutputStatistic(string name, int statistic, double statisticValue) |
| C++ | bool OptQuestModel::SetOutputStatistic(const char* name, int statistic, double statisticValue = 0) |
| C | int OQSetOutputStatistic(HOptQuestModel model, const char* name, int statistic, double statisticValue) |
| Python | bool OptQuestModel.set_output_statistic(str name, int statistic, float statistic_value=None) |
Description
Sets how the engine aggregates the output variable name across the replications of a trial. The setting is ignored when the model runs without replications. statistic is one of the values in the table below. statisticValue is used only with Percentile, where it selects the percentile as a fraction in [0, 1] (0.95 for the 95th percentile); a value outside that range is refused. The other statistics ignore it.
| Statistic | Java, C# | C++ | C, Python |
|---|---|---|---|
| None | OptQuestModel.Statistic.None |
OptQuestModel::Statistic::None |
OQStatisticNone |
| Mean | OptQuestModel.Statistic.Mean |
OptQuestModel::Statistic::Mean |
OQStatisticMean |
| Median | OptQuestModel.Statistic.Median |
OptQuestModel::Statistic::Median |
OQStatisticMedian |
| Percentile | OptQuestModel.Statistic.Percentile |
OptQuestModel::Statistic::Percentile |
OQStatisticPercentile |
| Standard Deviation | OptQuestModel.Statistic.StdDev |
OptQuestModel::Statistic::StdDev |
OQStatisticStdDev |
| Variance | OptQuestModel.Statistic.Variance |
OptQuestModel::Statistic::Variance |
OQStatisticVariance |
| Coefficient of Variation | OptQuestModel.Statistic.CoeffOfVar |
OptQuestModel::Statistic::CoeffOfVar |
OQStatisticCoeffOfVar |
| Min | OptQuestModel.Statistic.Min |
OptQuestModel::Statistic::Min |
OQStatisticMin |
| Max | OptQuestModel.Statistic.Max |
OptQuestModel::Statistic::Max |
OQStatisticMax |
| Sum | OptQuestModel.Statistic.Sum |
OptQuestModel::Statistic::Sum |
OQStatisticSum |
Notes
- The output variable must exist before this call.
- With
None, the result is the same as with no call: the engine uses the mean of the replications. An output that an objective with its own statistic reads is the exception. The engine does not combine that output, soGetValueon it returns the value of the replication that completed last. See § API Documentation › Objectives › Set Objective Statistic Parameters.
Add Output Vector Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddOutputVectorVariable(String name, int n) throws COptQuestException |
| C# | bool OptQuestModel.AddOutputVectorVariable(string name, int n) |
| C++ | bool OptQuestModel::AddOutputVectorVariable(const char* name, int n) |
| C | int OQAddOutputVectorVariable(HOptQuestModel model, const char* name, int n) |
| Python | bool OptQuestModel.add_output_vector_variable(str name, int n) |
Description
Adds an output vector variable: n output variables. The elements are ordinary output variables, and GetOutputNames returns their names.
The simulator writes a value to each element before it submits the solution.
Notes
- Variable names:
<name>@1to<name>@n, one for each element.
Add Output Matrix Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddOutputMatrixVariable(String name, int rows, int cols) throws COptQuestException |
| C# | bool OptQuestModel.AddOutputMatrixVariable(string name, int rows, int cols) |
| C++ | bool OptQuestModel::AddOutputMatrixVariable(const char* name, int rows, int cols) |
| C | int OQAddOutputMatrixVariable(HOptQuestModel model, const char* name, int rows, int cols) |
| Python | bool OptQuestModel.add_output_matrix_variable(str name, int rows, int cols) |
Description
Adds an output matrix variable: a rows by cols matrix of output variables. The elements are ordinary output variables, and GetOutputNames returns their names.
The simulator writes a value to each element before it submits the solution.
Notes
- Variable names:
<name>@<row>,<col>for each element, with 1-based row and column numbers, row by row. Each name contains a comma, so write it in brackets in an expression:[<name>@1,2].
Add Output ND Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddOutputNDVariable(String name, int[] dims) throws COptQuestException |
| C# | bool OptQuestModel.AddOutputNDVariable(string name, int[] dims) |
| C++ | bool OptQuestModel::AddOutputNDVariable(const char* name, const int* dims, int ndims) |
| C | int OQAddOutputNDVariable(HOptQuestModel model, const char* name, const int* dims, int ndims) |
| Python | bool OptQuestModel.add_output_nd_variable(str name, list[int] dims) |
Description
Adds an output N-dimensional variable: an array of output variables with the shape dims. The elements are ordinary output variables, and GetOutputNames returns their names.
The simulator writes a value to each element before it submits the solution.
Notes
- Variable names:
<name>@<i1>,<i2>,...for each element, with one 1-based index for each dimension. The last index changes fastest. With two or more dimensions, each name contains a comma, so write it in brackets in an expression:[<name>@1,2,3]. - In C and C++,
dimsis a pointer to an array ofndimsints.
Expression Variables
An expression variable is a derived value. The engine recomputes it from its formula after every evaluation.
Add Expression Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddExpressionVariable(String name, String expression) throws COptQuestException |
| C# | bool OptQuestModel.AddExpressionVariable(string name, string expression) |
| C++ | bool OptQuestModel::AddExpressionVariable(const char* name, const char* expression) |
| C | int OQAddExpressionVariable(HOptQuestModel model, const char* name, const char* expression) |
| Python | bool OptQuestModel.add_expression_variable(str name, str expression) |
Description
Adds an expression variable named name with the formula expression. The formula can reference input variables, output variables and expression variables that were added earlier. After every solution evaluation the engine recomputes the value. You can read it with OptQuestSolution.GetValue(name) and reference it in objectives, constraints, sample metrics and later expression variables. SetValue cannot assign it; the engine always derives it from the formula. The functions available in a formula are listed in § Reference › Functions and Constants Available In Expressions.
Notes
- An expression variable can reference other expression variables. The engine detects a circular dependency and reports an error when the model is initialized.
- Reference a container or special purpose variable by its element names, such as
dir@theta, not by its base name. A base name makes the model fail when it initializes. See § Concepts › Names. - An objective or a constraint that uses an expression variable is not linear, even when the formula of the expression variable is linear.
StopOnSuccessfulMILPhas no effect on such a model. To keep it in effect, write the formula into the objectives and constraints.
Variable Modifiers
Use the functions in this group on variables that already exist in the model. Add the variables first, then apply the modifier. Use an exclusive range to remove part of the domain of a variable. Use a selection variable to switch a group of variables on and off with one binary flag. Use an exchangeable group to declare identical items whose values you can exchange without a change to the result. Use a fix group or a float group to exploit structure in your problem by directing OptQuest to fix or float a group of variables during the search.
Add Exclusive Range to Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddVariableExclusiveRange(String name, double min, double max) throws COptQuestException |
| C# | bool OptQuestModel.AddVariableExclusiveRange(string name, double min, double max) |
| C++ | bool OptQuestModel::AddVariableExclusiveRange(const char* name, double min, double max) |
| C | int OQAddVariableExclusiveRange(HOptQuestModel model, const char* name, double min, double max) |
| Python | bool OptQuestModel.add_variable_exclusive_range(str name, float min_val, float max_val) |
Description
Excludes the open interval (min, max) from the domain of the variable name. The values min and max themselves stay feasible; only the values strictly between them are excluded. The variable must already exist. Call the function again to exclude another interval from the same variable.
Example
model.AddContinuousVariable("speed", 0, 100);
// Never run between 40 and 60: those speeds resonate with the structure
model.AddVariableExclusiveRange("speed", 40, 60);Add Selection Variable
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSelectionVariable(String name, String[] selVars) throws COptQuestException |
| C# | bool OptQuestModel.AddSelectionVariable(string name, string[] selVars) |
| C++ | bool OptQuestModel::AddSelectionVariable(const char* name, const char** selVars, int n) |
| C | int OQAddSelectionVariable(HOptQuestModel model, const char* name, const char** selVars, int n) |
| Python | bool OptQuestModel.add_selection_variable(str name, list[str] selVars) |
Description
Adds a binary input variable named name that gates a group of other variables. When the flag is 1, the variables in selVars take part in the optimization as usual. When the flag is 0, the engine sets each of them to its lower bound for that solution. Every variable in selVars must already exist.
Example
model.AddContinuousVariable("pump_size", 10, 50);
model.AddIntegerVariable("pump_count", 1, 4);
// "use_pump" is a new binary variable. When it is 0, pump_size is 10 and pump_count is 1.
model.AddSelectionVariable("use_pump", new String[]{"pump_size", "pump_count"});Notes
- In C and C++,
selVarsis a pointer to an array ofnstrings. - This function gates a group of variables on one binary flag. For a k-of-n selection over a flat pool of items, use the Item Selection Variable instead.
Add Exchangeable Group
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddExchangeableGroup(String name, String[] variables) throws COptQuestExceptionboolean OptQuestModel.AddExchangeableGroup(String name, String[][] variables) throws COptQuestException |
| C# | bool OptQuestModel.AddExchangeableGroup(string name, string[] variables)bool OptQuestModel.AddExchangeableGroup(string name, string[][] group) |
| C++ | bool OptQuestModel::AddExchangeableGroup(const char* name, const char** variables, int n)bool OptQuestModel::AddExchangeableGroup(const char* name, const char*** group, int ng, int nv) |
| C | int OQAddExchangeableGroupFlat(HOptQuestModel model, const char* name, const char** variables, int n)int OQAddExchangeableGroup(HOptQuestModel model, const char* name, const char*** group, int ng, int nv) |
| Python | bool OptQuestModel.add_exchangeable_group(str name, list[str] | list[list[str]] group) |
Description
Declares a group named name of identical items whose values you can exchange without a change to the result. In each trial solution that the optimizer generates, it puts the items in ascending order of their values, in the order that you list them. Thus the optimizer does not evaluate two solutions that differ only by an exchange of items. This call adds no variable to the model.
There are two forms. The flat form takes a list of variable names, one variable for each item. In each trial solution that the optimizer generates, the first variable in the list has the smallest value. The grouped form takes a list of rows. Each row holds the variables of one item, and every row has the same number of variables in the same order. The optimizer orders the rows by the value of their first variable, then by the second variable when the first values are equal, and so on. In Python one function covers both forms: a flat sequence of strings selects the flat form, and a sequence of sequences selects the grouped form. In C they are separate entry points, OQAddExchangeableGroupFlat and OQAddExchangeableGroup.
A common use is placing several identical items. For example, three identical machines in a factory, each with a location to optimize:
model.AddContinuousVariable("machine1_x", min_x, max_x);
model.AddContinuousVariable("machine1_y", min_y, max_y);
model.AddContinuousVariable("machine2_x", min_x, max_x);
model.AddContinuousVariable("machine2_y", min_y, max_y);
model.AddContinuousVariable("machine3_x", min_x, max_x);
model.AddContinuousVariable("machine3_y", min_y, max_y);
model.AddExchangeableGroup("machines", new String[][]{{"machine1_x","machine1_y"},
{"machine2_x","machine2_y"},
{"machine3_x","machine3_y"},
});With the group, the optimizer has fewer solutions to search. Three integer variables from 0 to 4 have 125 combinations of values, and 35 of them are different when the order does not matter. Without a group, the optimizer will evaluate all 125 combinations and then stop with the termination reason OptimalFound (5). With an exchangeable group defined, it will evaluate only combinations and then stop with the same reason.
Use an exchangeable group only for items that have the same type, the same bounds and the same role in your evaluation. If the items differ but they are added to an exchangable group, for example machines with different capacities, two solutions with the two items exchanged are different solutions, but the optimizer will evaluate only one of them.
Notes
- Each member must be a decision variable that is already in the model: a continuous, integer, discrete, binary, design, enumeration, tuple, geolocation or selection variable, or an element of a vector, matrix, N-dimensional, item-selection or budgeted-selection variable under its generated name, such as
v@1,m@1,2orn@1,2,3. The values of a special purpose variable, such asdir@theta, are not accepted. Names are matched without regard to case. - Put a variable in no more than one exchangeable group. The call accepts a variable that is already in another group, but the order of the second group can break the order of the first. In a test with the groups (a, b) and (b, c), a was greater than b in 20 of the 55 evaluated solutions.
- The optimizer evaluates a solution that you give with Add Suggested with the values that you give, in any order.
- Java returns
falseif the model is already initialized, if the name is not valid or is already in use, or if a member is not an accepted decision variable of the model. If the rows do not all have the same number of variables, Java throws aCOptQuestExceptionwith the message “Variable definitions are of unequal length.” Python raisesValueErrorfor rows of different lengths. - Outside Java, the call returns the failure value, and
GetLastError()returns one of these messages:ERROR the model has no input variable named <name>for a member name without@that is not a decision variable of the kinds above, for example the base name of a vector variable, a random variable, an output variable or an expression variable.ERROR <name> is not a variable that a group can holdfor a member name with@that is not an element of the kinds above: for example the valuedir@thetaof an angle variable, the value of a mixture, sequence, choice or other special purpose variable, an element outside the size of its variable such asv@4for a vector of 3 elements, or a name that no variable of the model generates.ERROR group member names cannot be empty or contain whitespace or semicolonfor an empty member name or a member name that holds whitespace or a semicolon.ERROR a comma in an exchangeable group member must be followed by a digitfor a member name such asa,b. In the model definition, the members of a group are joined with commas, and the engine joins a part that starts with a digit to the member before it, because a variable name cannot start with a digit. Every generated element name has a digit after each comma. This message applies only to an exchangeable group.ERROR n must be at least 1for an empty flat list, andERROR ng must be at least 1orERROR nv must be at least 1for a grouped form with no rows or with empty rows.ERROR duplicate name,ERROR name cannot be empty or contain whitespace or semicolonorERROR already initializedfor the group name and the model state.
- In C and C++,
groupis a pointer to an array ofnggroups, each a pointer tonvstrings.
Add Fix Group
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddFixGroup(String name, String[] variables) throws COptQuestException |
| C# | bool OptQuestModel.AddFixGroup(string name, string[] variables) |
| C++ | bool OptQuestModel::AddFixGroup(const char* name, const char** variables, int n) |
| C | int OQAddFixGroup(HOptQuestModel model, const char* name, const char** variables, int n) |
| Python | bool OptQuestModel.add_fix_group(str name, list[str] variables) |
Description
Declares a fix group named name: AddFixGroup can help OptQuest exploit structure in a problem by directing OptQuest to fix a group of variables during the search. In some generated solutions later in the search, the variables of the fix group will be assigned values based on the best solution found so far, while the other variables are given new values. Use a fix group when you want diversity in the search to focus on the other variables.
A fix group of a set of variables gives the same trial solutions as a float group of all the other variables, so declare the smaller set.
Example
// Search the rest of the model with the three pump settings held at
// their values in the best solution found so far.
model.AddFixGroup("pumps", new String[]{"pump1", "pump2", "pump3"});Notes
- Each member must be a decision variable that is already in the model, of the same kinds as for Add Exchangeable Group. Names are matched without regard to case.
- For each group that you add, the optimizer makes its own trial solutions. The call accepts a variable that is already in another group.
- An empty list of members is accepted.
- Java returns
falseif the model is already initialized, if the name is not valid or is already in use, or if a member is not an accepted decision variable of the model. Outside Java, the call returns the failure value with the messages listed for Add Exchangeable Group. - In C and C++,
variablesis a pointer to an array ofnstrings.
Add Float Group
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddFloatGroup(String name, String[] variables) throws COptQuestException |
| C# | bool OptQuestModel.AddFloatGroup(string name, string[] variables) |
| C++ | bool OptQuestModel::AddFloatGroup(const char* name, const char** variables, int n) |
| C | int OQAddFloatGroup(HOptQuestModel model, const char* name, const char** variables, int n) |
| Python | bool OptQuestModel.add_float_group(str name, list[str] variables) |
Description
Declares a float group named name: AddFloatGroup can help OptQuest exploit structure in a problem by directing OptQuest to float a group of variables during the search. A float group is the inverse of a fix group. In some generated solutions later in the search, the float variables will take new values, while and the other variables will be assigned values based on the best solution found so far. Use a float group when you want diversity in the search to focus on these variables.
A fix group of a set of variables gives the same trial solutions as a float group of all the other variables, so declare the smaller set.
Example
// Search the two setpoints with every other variable held at its value
// in the best solution found so far.
model.AddFloatGroup("setpoints", new String[]{"t1", "t2"});Notes
- Each member must be a decision variable that is already in the model, of the same kinds as for Add Exchangeable Group. Names are matched without regard to case.
- For each group that you add, the optimizer makes its own trial solutions. The call accepts a variable that is already in another group.
- An empty list of members is accepted.
- Java returns
falseif the model is already initialized, if the name is not valid or is already in use, or if a member is not an accepted decision variable of the model. Outside Java, the call returns the failure value with the messages listed for Add Exchangeable Group. - In C and C++,
variablesis a pointer to an array ofnstrings.
Objectives
Add Objective
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddMinimizeObjective(String name, String expression)boolean OptQuestModel.AddMaximizeObjective(String name, String expression)boolean OptQuestModel.AddObjective(String name, String dir, String expression) |
| C# | bool OptQuestModel.AddMinimizeObjective(string name, string expression)bool OptQuestModel.AddMaximizeObjective(string name, string expression)bool OptQuestModel.AddObjective(string name, string direction, string expression) |
| C++ | bool OptQuestModel::AddMinimizeObjective(const char* name, const char* expression)bool OptQuestModel::AddMaximizeObjective(const char* name, const char* expression)bool OptQuestModel::AddObjective(const char* name, const char* direction, const char* expression) |
| C | int OQAddMinimizeObjective(HOptQuestModel model, const char* name, const char* expression)int OQAddMaximizeObjective(HOptQuestModel model, const char* name, const char* expression)int OQAddObjective(HOptQuestModel model, const char* name, const char* direction, const char* expression) |
| Python | bool OptQuestModel.add_minimize_objective(str name, str expression)bool OptQuestModel.add_maximize_objective(str name, str expression)bool OptQuestModel.add_objective(str name, str direction, str expression) |
Description
Adds an objective named name that minimizes or maximizes expression. AddMinimizeObjective and AddMaximizeObjective are shorthand for AddObjective with the direction MIN or MAX. direction accepts only those two tokens, in any case; the call fails for any other token. expression is a formula over input and output variables. The functions it can use are listed in § Reference › Functions and Constants Available In Expressions. When the model has more than one objective, OptQuest runs a multi-objective optimization and produces a Pareto frontier of trade-off solutions.
Set Multi-Objective Goal
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetObjectiveGoal(String name, double min, double max) |
| C# | bool OptQuestModel.SetObjectiveGoal(string name, double min, double max) |
| C++ | bool OptQuestModel::SetObjectiveGoal(const char* name, double min, double max) |
| C | int OQSetObjectiveGoal(HOptQuestModel model, const char* name, double min, double max) |
| Python | bool OptQuestModel.set_objective_goal(str name, float min_val, float max_val) |
Description
Sets a target range for the objective name in a multi-objective optimization. The range is from min to max inclusive. The objective must already exist. OptQuest uses the goal to decide where to search. After its first cycle of search phases, OptQuest uses the rest of the run to fill gaps between neighboring solutions on the Pareto frontier, while the frontier has at least two solutions. It fills first the largest gap next to a frontier solution whose objective values are inside the most goal ranges. When no frontier solution is inside every range, OptQuest uses the solutions that are inside the most ranges.
OptQuest does not use the goal to decide feasibility, and it does not remove the solutions outside the range from the Pareto frontier. The frontier that GetBestSolutions returns can include solutions outside the range. The setting is ignored in a single-objective model.
Set Objective Statistic Parameters
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetObjectiveStatistic(String name, int statistic) throws COptQuestExceptionboolean OptQuestModel.SetObjectiveStatistic(String name, int statistic, double statisticValue) throws COptQuestException |
| C# | bool OptQuestModel.SetObjectiveStatistic(string name, int statistic)bool OptQuestModel.SetObjectiveStatistic(string name, int statistic, double statisticValue) |
| C++ | bool OptQuestModel::SetObjectiveStatistic(const char* name, int statistic, double statisticValue = 0) |
| C | int OQSetObjectiveStatistic(HOptQuestModel model, const char* name, int statistic, double statisticValue) |
| Python | bool OptQuestModel.set_objective_statistic(str name, int statistic, float statistic_value=None) |
Description
Sets how the engine aggregates the objective name across the replications of a trial. The setting is ignored when the model runs without replications. statistic is one of the values in the table below. statisticValue is used only with Percentile, where it selects the percentile as a fraction in [0, 1] (0.95 for the 95th percentile); a value outside that range is refused. The other statistics ignore it.
| Statistic | Java, C# | C++ | C, Python |
|---|---|---|---|
| None | OptQuestModel.Statistic.None |
OptQuestModel::Statistic::None |
OQStatisticNone |
| Mean | OptQuestModel.Statistic.Mean |
OptQuestModel::Statistic::Mean |
OQStatisticMean |
| Median | OptQuestModel.Statistic.Median |
OptQuestModel::Statistic::Median |
OQStatisticMedian |
| Percentile | OptQuestModel.Statistic.Percentile |
OptQuestModel::Statistic::Percentile |
OQStatisticPercentile |
| Standard Deviation | OptQuestModel.Statistic.StdDev |
OptQuestModel::Statistic::StdDev |
OQStatisticStdDev |
| Variance | OptQuestModel.Statistic.Variance |
OptQuestModel::Statistic::Variance |
OQStatisticVariance |
| Coefficient of Variation | OptQuestModel.Statistic.CoeffOfVar |
OptQuestModel::Statistic::CoeffOfVar |
OQStatisticCoeffOfVar |
| Min | OptQuestModel.Statistic.Min |
OptQuestModel::Statistic::Min |
OQStatisticMin |
| Max | OptQuestModel.Statistic.Max |
OptQuestModel::Statistic::Max |
OQStatisticMax |
| Sum | OptQuestModel.Statistic.Sum |
OptQuestModel::Statistic::Sum |
OQStatisticSum |
Notes
- The objective must exist before this call.
- With
None, or with no call, the engine combines each output that the objective reads across the replications, with the statistic of that output (the mean unlessSetOutputStatisticsets another). Then it computes the objective expression once from those values. For an objectivey*yand two replications with y = 1 and y = 3, the objective is 4.0. - With any other statistic, the engine computes the objective expression in each replication and applies the statistic to those values. For the same replications,
Meangives 5.0 andMaxgives 9.0. The engine does not combine an output that such an objective reads, soGetValueon that output returns the value of the replication that completed last. - A statistic on the objective and a statistic other than
Noneon an output that the objective reads are refused together. The model fails when it initializes, with the message “You have defined a statistic on a COptQuestStringObjective and the expression contains a COptQuestUserControlledVariable that also contains a statistic.”
Set Objective Confidence Parameters
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetObjectiveConfidence(String name, int ctype, int clevel, double epct) |
| C# | bool OptQuestModel.SetObjectiveConfidence(string name, int ctype, int clevel, double epct) |
| C++ | bool OptQuestModel::SetObjectiveConfidence(const char* name, int ctype, int clevel, double epct) |
| C | int OQSetObjectiveConfidence(HOptQuestModel model, const char* name, int ctype, int clevel, double epct) |
| Python | bool OptQuestModel.set_objective_confidence(str name, int ctype, int clevel, float epct) |
Description
Sets the early-stopping confidence parameters for the objective name in a variable-replication optimization. The setting is ignored when the replication count is fixed or the model runs without replications. The parameters are:
ctype: the confidence type, from the first table below.clevel: the confidence level, from the second table below.epct: the acceptable error, as a fraction of the mean of the replications. It must be greater than 0 and less than 1. For 5 percent, pass0.05. The engine checks the value when the model initializes, not at this call. With a value outside that range, the run fails with the message “Bad value for the replication confidence error percent.”
With these set, OptQuest stops replicating a trial solution when the half-width of the confidence interval at the level clevel is at most epct times the absolute value of the mean of the replications.
Confidence testing works only with the mean. If the objective, or an output that it uses, has a statistic other than Mean, the model fails when it initializes, with the message “You must use the Mean statistic when using replication confidence.” With no statistic set, the engine uses the mean.
ctype selects one of two rules. Type 1 continues replicating until the confidence level is reached or the maximum number of replications is run. Type 2 also stops early when OptQuest determines that the current solution cannot fall within the confidence interval of the best solution. Type 2 applies to single-objective models.
| Confidence Type | Java, C# | C++ | C, Python |
|---|---|---|---|
| Type 1 | OptQuestModel.Confidence.Type1 |
OptQuestModel::Confidence::Type1 |
OQConfidenceType1 |
| Type 2 | OptQuestModel.Confidence.Type2 |
OptQuestModel::Confidence::Type2 |
OQConfidenceType2 |
clevel selects the confidence level of the interval:
| Confidence Level | Java, C# | C++ | C, Python |
|---|---|---|---|
| 80% | OptQuestModel.Confidence.Level80 |
OptQuestModel::Confidence::Level80 |
OQConfidenceLevel80 |
| 90% | OptQuestModel.Confidence.Level90 |
OptQuestModel::Confidence::Level90 |
OQConfidenceLevel90 |
| 95% | OptQuestModel.Confidence.Level95 |
OptQuestModel::Confidence::Level95 |
OQConfidenceLevel95 |
| 98% | OptQuestModel.Confidence.Level98 |
OptQuestModel::Confidence::Level98 |
OQConfidenceLevel98 |
| 99% | OptQuestModel.Confidence.Level99 |
OptQuestModel::Confidence::Level99 |
OQConfidenceLevel99 |
| 99.9% | OptQuestModel.Confidence.Level999 |
OptQuestModel::Confidence::Level999 |
OQConfidenceLevel999 |
Notes
- The objective must exist before this call.
Constraints
Add Constraint
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddConstraint(String name, String expression) throws COptQuestException |
| C# | bool OptQuestModel.AddConstraint(string name, string expression) |
| C++ | bool OptQuestModel::AddConstraint(const char* name, const char* expression) |
| C | int OQAddConstraint(HOptQuestModel model, const char* name, const char* expression) |
| Python | bool OptQuestModel.add_constraint(str name, str expression) |
Description
Adds a constraint named name with the formula expression. The formula can reference input variables, output variables, expression variables and objectives, and it can be linear or non-linear. The functions it can use are listed in § Reference › Functions and Constants Available In Expressions.
Notes
- A constraint that references only input variables is enforced before the evaluator runs, so the simulator never sees an infeasible input. A constraint that references an output variable is checked after evaluation, and the solution is marked infeasible if it fails. See § Concepts › Model Components › Constraints.
- A constraint over the variable names of a special purpose variable, other than an Item Selection or a Budgeted Selection variable, is checked after evaluation. See § Decision Variables › Special Purpose Variables: Common Behavior.
- Reference a container or special purpose variable by its element names, such as
dir@theta, not by its base name. A base name, as indir <= 7, makes the model fail when it initializes. See § Concepts › Names. - The engine reads
<as<=and>as>=. A solution on the bound satisfiesx + y < 7. - When the bound is a constant, the engine accepts a small violation. For a linear constraint over input variables only, the tolerance is 1e-5 for each variable in the constraint, and the engine applies it to the value of the expression with its coefficients.
x + y <= 7accepts x + y up to 7.00002, and10*x + 10*y <= 70accepts 10x + 10y up to 70.00002. For a constraint that reads an output variable, and for a non-linear constraint, the tolerance is 1e-5 on the value of the expression. The engine uses the same tolerances for>=and=.
Adaptive Sampling Configuration
Add Sampling Metric
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddSampleMetric(String name, String responseExpression, String errorExpression) |
| C# | bool OptQuestModel.AddSampleMetric(string name, string response, string error) |
| C++ | bool OptQuestModel::AddSampleMetric(const char* name, const char* response, const char* error) |
| C | int OQAddSampleMetric(HOptQuestModel model, const char* name, const char* response, const char* error) |
| Python | bool OptQuestModel.add_sample_metric(str name, str response, str error) |
Description
Adds a sampling metric named name for Adaptive Sampling. responseExpression is a formula over input and output variables that gives the response the sampler tracks. errorExpression is a formula that gives the uncertainty (error) of that response; pass "0" when the response is exact. The functions the formulas can use are listed in § Reference › Functions and Constants Available In Expressions. The engine creates two values, <name>@response and <name>@error, that you can read from a solution and reference in expressions.
model.AddSampleMetric("metric", response, error);This creates metric@response and metric@error.
Notes
- Both expressions are required. The binding sends the two to the engine on one line, joined by
;, so the call refuses an empty or whitespace-onlyresponseExpressionorerrorExpression, and refuses a;inside either. - The engine uses the metric only during Adaptive Sampling and ignores it in an optimization.
Set Sampling Method
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetSampleMethod(int method) |
| C# | bool OptQuestModel.SetSampleMethod(int method) |
| C++ | bool OptQuestModel::SetSampleMethod(int method) |
| C | int OQSetSampleMethod(HOptQuestModel model, int method) |
| Python | bool OptQuestModel.set_sample_method(int method) |
Description
Sets the sampling method for Adaptive Sampling. method is a bitwise OR of the flags in the table below. The flags determine how the sampling engine builds its internal model and selects the next sample points. See § Adaptive Sampling for the strategies.
| Method | Java, C# | C++ | C, Python |
|---|---|---|---|
| Stochastic | OptQuestModel.SampleMethod.Stochastic |
OptQuestModel::SampleMethod::Stochastic |
OQSampleMethodStochastic |
| Dynamic | OptQuestModel.SampleMethod.Dynamic |
OptQuestModel::SampleMethod::Dynamic |
OQSampleMethodDynamic |
| Async | OptQuestModel.SampleMethod.Async |
OptQuestModel::SampleMethod::Async |
OQSampleMethodAsync |
| Uniform | OptQuestModel.SampleMethod.Uniform |
OptQuestModel::SampleMethod::Uniform |
OQSampleMethodUniform |
| Variance | OptQuestModel.SampleMethod.Variance |
OptQuestModel::SampleMethod::Variance |
OQSampleMethodVariance |
| Zero | OptQuestModel.SampleMethod.Zero |
OptQuestModel::SampleMethod::Zero |
OQSampleMethodZero |
| Gradient | OptQuestModel.SampleMethod.Gradient |
OptQuestModel::SampleMethod::Gradient |
OQSampleMethodGradient |
| Min | OptQuestModel.SampleMethod.Min |
OptQuestModel::SampleMethod::Min |
OQSampleMethodMin |
| Max | OptQuestModel.SampleMethod.Max |
OptQuestModel::SampleMethod::Max |
OQSampleMethodMax |
| Response Distribution | OptQuestModel.SampleMethod.RDS |
OptQuestModel::SampleMethod::RDS |
OQSampleMethodRDS |
| Stochastic + feedback | OptQuestModel.SampleMethod.Stochastic<Method> |
OptQuestModel::SampleMethod::Stochastic<Method> |
OQSampleMethodStochastic<Method> |
The Stochastic<Method> constants (StochasticVariance, StochasticUniform, StochasticZero, StochasticGradient, StochasticMin, StochasticMax, StochasticRDS) are shorthand for Stochastic | Async | <Method>, the usual combination for a stochastic simulation. Every language has the same names.
Sampling Method Categories
The flags fall into two groups. The model-building flags (Stochastic, Dynamic, Async) control how the engine builds its internal model. The feedback flags (Uniform, Variance, Zero, Gradient, Min, Max, RDS) control how it selects the next sample point.
Model-Building Methods
- Stochastic: When this flag is off (the default), the engine searches for the single best next sample point, which can focus too narrowly and can be expensive. When it is on, the engine draws the next point at random from the domain, weighted by predicted quality. The engine then explores more of the domain and produces points faster.
- Dynamic: For a fast simulation, building the internal model can take longer than an evaluation. When this flag is on, the engine monitors the evaluation times and generates several sample points at once to keep the simulations busy, at some cost in model accuracy.
- Async: When this flag is on, the engine builds the internal model on a background thread, so model building and evaluation overlap. If a new point is requested before the model is updated, the engine uses the previous model. With a fast simulation, the engine completes more evaluations in the same time when this flag is on.
Feedback Methods
These flags define the criterion for the next sample point, based on the metric’s estimated value and uncertainty. Several feedback flags can be combined with bitwise OR. The engine then produces one sample per enabled flag per request.
- Uniform: distributes the samples evenly across the domain with a space-filling sequence and ignores the metric. This is the fastest way to cover the domain.
- Variance: samples where the variance is highest (the least-known areas). With this flag the engine reduces the global variance and builds a response surface that is accurate everywhere.
- Zero: samples where the metric is closest to zero, to map boundaries and transition zones.
- Gradient: samples where the response changes fastest.
- Min: samples densely where the metric is smallest.
- Max: samples densely where the metric is largest.
- RDS: samples where more points are needed to reach the wanted probability distribution. See § Reference › Probability Distributions. When RDS is included, you must also set the wanted distribution with one of the
SetSampleRDS*functions.
Set Sampling Variogram
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetSampleVariogram(String variogram) |
| C# | bool OptQuestModel.SetSampleVariogram(string variogram) |
| C++ | bool OptQuestModel::SetSampleVariogram(const char* variogram) |
| C | int OQSetSampleVariogram(HOptQuestModel model, const char* variogram) |
| Python | bool OptQuestModel.set_sample_variogram(str variogram) |
Description
Sets the variogram that the engine uses to build the internal surrogate model during Adaptive Sampling. By default the engine chooses a variogram with a heuristic. Call this function to select one of the variograms in the table below instead. Most users do not need this function: use the default unless OptTek support advises a different variogram.
| Method | Java, C# | C++ | C, Python |
|---|---|---|---|
| Spherical | OptQuestModel.SampleVariogram.Spherical |
OptQuestModel::SampleVariogram::Spherical |
OQSampleVariogramSpherical |
| Pow | OptQuestModel.SampleVariogram.Pow |
OptQuestModel::SampleVariogram::Pow |
OQSampleVariogramPow |
| Exp | OptQuestModel.SampleVariogram.Exp |
OptQuestModel::SampleVariogram::Exp |
OQSampleVariogramExp |
| Gaussian | OptQuestModel.SampleVariogram.Gaussian |
OptQuestModel::SampleVariogram::Gaussian |
OQSampleVariogramGaussian |
| Tanh | OptQuestModel.SampleVariogram.Tanh |
OptQuestModel::SampleVariogram::Tanh |
OQSampleVariogramTanh |
| Sech | OptQuestModel.SampleVariogram.Sech |
OptQuestModel::SampleVariogram::Sech |
OQSampleVariogramSech |
| Linear | OptQuestModel.SampleVariogram.Linear |
OptQuestModel::SampleVariogram::Linear |
OQSampleVariogramLinear |
| Quadratic | OptQuestModel.SampleVariogram.Quadratic |
OptQuestModel::SampleVariogram::Quadratic |
OQSampleVariogramQuadratic |
| Partition | OptQuestModel.SampleVariogram.Partition |
OptQuestModel::SampleVariogram::Partition |
OQSampleVariogramPartition |
| Matern | OptQuestModel.SampleVariogram.Matern |
OptQuestModel::SampleVariogram::Matern |
OQSampleVariogramMatern |
Notes
- The variogram is a string. In C and C++, the
OQSampleVariogram*andOptQuestModel::SampleVariogram::*constants are string literals; pass them directly.
Set Response Distribution
These functions set the wanted probability distribution for a Response Distribution Sampling (RDS) metric. Set exactly one distribution per metric with the matching SetSampleRDS<DistName> function. The setting takes effect only when RDS is part of the sampling method (see § Set Sampling Method); otherwise the engine ignores it.
For a continuous distribution, the engine divides the support into nBins bins of equal probability under that distribution and biases the sampling toward the bins that are under-represented among the evaluated responses. For the discrete distribution, you give the bin edges directly. See § Reference › Probability Distributions for the algorithm.
Function Signatures
name identifies the sample metric declared with AddSampleMetric. nBins is the number of equal-probability bins for a continuous distribution. The remaining parameters depend on the distribution:
| Distribution | Function Name | Distribution-Specific Parameters |
|---|---|---|
| Uniform | SetSampleRDSUniform |
double a, double b: lower and upper bounds of the uniform distribution |
| Normal | SetSampleRDSNormal |
double mu, double sigma: mean and standard deviation |
| Log Normal | SetSampleRDSLogNormal |
double s, double scale: shape and scale parameters |
| Beta | SetSampleRDSBeta |
double alpha, double beta: shape parameters |
| Poisson | SetSampleRDSPoisson |
double lambda: rate parameter |
| Exponential | SetSampleRDSExponential |
double scale: scale parameter (inverse rate) |
| Cauchy | SetSampleRDSCauchy |
double location, double scale: location (median) and scale parameters |
| Gamma | SetSampleRDSGamma |
double a, double scale: shape and scale parameters |
| Chi-Square | SetSampleRDSChiSquare |
double nu: degrees of freedom |
| Pareto | SetSampleRDSPareto |
double gamma, double loc, double scale: shape, location, and scale parameters |
| Student’s t | SetSampleRDST |
double nu: degrees of freedom |
| Weibull | SetSampleRDSWeibull |
double c, double scale: shape and scale parameters |
| Discrete | SetSampleRDSDiscrete |
double[] binEdges: n - 1 edges defining n bins; the outermost bins extend to -infinity and +infinity |
The Java signature of each continuous form is boolean OptQuestModel.SetSampleRDS<DistName>(String name, int nBins, <distribution parameters>). The discrete form has no nBins and takes a double[] binEdges instead. The other languages follow their usual conventions. In C each function is int OQSetSampleRDS<DistName>(HOptQuestModel model, const char* name, int nBins, ...), for example OQSetSampleRDSNormal(model, name, nBins, mu, sigma), and the discrete form is int OQSetSampleRDSDiscrete(HOptQuestModel model, const char* name, const double* binEdges, int nBinEdges). In Python the names are lower case with underscores, for example set_sample_rds_normal(name, nBins, mu, sigma).
Every one of these functions is a wrapper over one generic entry point:
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetSampleRDSParams(String name, String distribution, double[] params) |
| C# | bool OptQuestModel.SetSampleRDSParams(string name, string distribution, double[] rdsParams) |
| C++ | bool OptQuestModel::SetSampleRDSParams(const char* name, const char* distribution, const double* rdsParams, int nParams) |
| C | int OQSetSampleRDSParams(HOptQuestModel model, const char* name, const char* distribution, const double* rdsParams, int nParams) |
| Python | bool OptQuestModel.set_sample_rds_params(str name, str distribution, Sequence[float] rdsParams) |
distribution is one of UNIFORM, NORMAL, LOGNORMAL, BETA, POISSON, EXPONENTIAL, CAUCHY, GAMMA, CHISQUARE, PARETO, T, WEIBULL or DISCRETE (case-insensitive). For every distribution except DISCRETE, params[0] is the bin count and the remaining entries are the distribution parameters in the order of the table above. For DISCRETE the whole array is the bin edges. Prefer the named functions; they place the arguments for you.
Discrete Distribution Example
For a wanted distribution on [0, 1] split into 10 bins of equal width, pass binEdges = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]. The bins are (-infinity, 0.1), [0.1, 0.2), …, [0.8, 0.9), [0.9, +infinity). During sampling the engine biases the points toward the bin with the lowest count, so a narrower bin gets a higher sampling density.
Notes
- In C and C++,
binEdgesis a pointer to an array ofnBinEdgesdoubles.
Optimization Configuration
Set Replications
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetReplications(int reps)boolean OptQuestModel.SetReplications(int min, int max) |
| C# | bool OptQuestModel.SetReplications(int reps)bool OptQuestModel.SetReplications(int min, int max) |
| C++ | bool OptQuestModel::SetReplications(int reps)bool OptQuestModel::SetReplications(int min, int max) |
| C | int OQSetReplications(HOptQuestModel model, int min, int max) |
| Python | bool OptQuestModel.set_replications(int min_reps, int max_reps=None) |
Description
Sets how many replications OptQuest runs for each trial solution of a stochastic optimization. There are two modes:
- Fixed replications:
SetReplications(reps)runs exactlyrepsreplications for every trial. C has no single-argument form; pass the same value asminandmax. - Variable replications:
SetReplications(min, max)lets OptQuest decide how many replications to run, betweenminandmaxinclusive. The replications stop early when the objective meets the confidence set withSetObjectiveConfidence. WithoutSetObjectiveConfidence, the engine runsmaxreplications for every trial solution. In Python one method covers both modes: omitmax_repsfor fixed mode, or supply it for variable mode.
min must be at least 1 and max at least min; other values are rejected. A max of 1 runs without replications. A min of 1 with a larger max runs at least two replications per trial, because a confidence interval needs two observations.
Notes
- Variable replications need
SetObjectiveConfidenceon an objective.SetObjectiveStatisticandSetOutputStatisticset how the engine combines the replications into one value. They do not stop the replications early.
Set Serial Replications
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetSerialReplications() |
| C# | bool OptQuestModel.SetSerialReplications() |
| C++ | bool OptQuestModel::SetSerialReplications() |
| C | int OQSetSerialReplications(HOptQuestModel model) |
| Python | bool OptQuestModel.set_serial_replications() |
Description
Turns on serial replication mode, which changes how the engine schedules replications when several solutions are evaluated in parallel. By default the engine completes every replication of one solution before it generates the next. In serial replication mode the engine generates and evaluates the next solution as soon as the first replication result arrives, so the replications of different solutions interleave across the parallel evaluators. Most users do not need this function. It has an effect only on a model with replications whose solutions are evaluated in parallel.
Notes
- The setting matters only when several solutions are evaluated in parallel, for example in a concurrent optimization.
Set Parallel Hint
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetParallelHint(int npar) |
| C# | bool OptQuestModel.SetParallelHint(int npar) |
| C++ | bool OptQuestModel::SetParallelHint(int npar) |
| C | int OQSetParallelHint(HOptQuestModel model, int npar) |
| Python | bool OptQuestModel.set_parallel_hint(int npar) |
Description
Tells the engine that about npar solutions will be out for evaluation at a time in a manual optimization. Some of the internal metaheuristics depend on that number. The search is most efficient when the number of solutions evaluated in parallel matches the hint, but any number of solutions, up to 5000, can be out at once. Most users do not need this function. It has an effect only in a manual loop with several solutions out at once.
Notes
- The setting applies only to manual optimization. In managed optimization the number of parallel evaluators is a parameter of
Optimize, and the engine uses that value. - If the number of solutions out for evaluation varies, for example with load balancing, set
nparto between one half and two thirds of the largest expected number.
Set Random Seed
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetRandomSeed(int seed) |
| C# | bool OptQuestModel.SetRandomSeed(int seed) |
| C++ | bool OptQuestModel::SetRandomSeed(int seed) |
| C | int OQSetRandomSeed(HOptQuestModel model, int seed) |
| Python | bool OptQuestModel.set_random_seed(int seed) |
Description
Sets the random seed the engine uses during an optimization. Use it to find out how much a result depends on the random choices of the search: run the same model with several seeds and compare the best objective values.
Notes
- By default the engine always uses the same seed, so an optimization is repeatable. Set a different seed to make the engine take a different path through the search.
seedmust be greater than 0. A seed of 0 or less is accepted but ignored, and the default seed is used.
Stop On Successful MILP
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.StopOnSuccessfulMILP() |
| C# | bool OptQuestModel.StopOnSuccessfulMILP() |
| C++ | bool OptQuestModel::StopOnSuccessfulMILP() |
| C | int OQStopOnSuccessfulMILP(HOptQuestModel model) |
| Python | bool OptQuestModel.stop_on_successful_milp() |
Description
Tells the engine to stop an optimization early when its internal linear-programming solver solves the problem exactly, which happens when the objective and the constraints are linear in the inputs. The engine ignores the setting when the objective or a constraint is non-linear.
Suggested Solutions Only
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SuggestedSolutionsOnly() |
| C# | bool OptQuestModel.SuggestedSolutionsOnly() |
| C++ | bool OptQuestModel::SuggestedSolutionsOnly() |
| C | int OQSuggestedSolutionsOnly(HOptQuestModel model) |
| Python | bool OptQuestModel.suggested_solutions_only() |
Description
Restricts the model to the solutions the caller supplies. OptQuest evaluates the solutions added with AddSuggested, AddEvaluated and AddRequired and generates none of its own.
The engine still changes the input values of each suggested solution so that they satisfy the input-only constraints and the rules of each variable type, and it still drops duplicates. So you can supply a set of points, and CreateSolution returns the distinct feasible solutions that the engine makes from them. Two points that give the same feasible solution (an integer variable given 1.1 and 1.2, for example) give one solution, and the engine drops the duplicate. When the supplied solutions run out, CreateSolution returns an invalid solution and GetTerminationReason reports FactoriesDone, so the caller reads back all the remaining solutions without knowing the count in advance.
Notes
- Use this mode with the manual
CreateSolutionloop, not withOptimize. Running out of supplied solutions is the normal end of such a run, but the serialOptimize(nsol, ...)overload reports it as a failure: it returnsfalsewhen the supplied solutions are exhausted beforensolis reached, without an exception and with no error message, so a successful run cannot be told apart from a real failure. The parallelOptimize(npar, nsol, ...)overload returnstruein the same situation. Because the caller does not know in advance how many distinct feasible solutions the engine makes,nsolis almost always larger than that number. - The model still needs an objective. A model used this way typically declares a placeholder objective over any output.
- Every solution that
CreateSolutionreturns must go back to the engine withSubmitorReject.Rejectis the usual choice when the changed input values are the only result wanted. - Duplicate checking covers the whole run, not one batch. After a solution is returned to the engine, the engine drops every later suggestion on that model that duplicates it. Use a separate model for each set of points to process independently.
- The engine also drops a suggested solution for which it cannot find feasible input values, in the same way as a duplicate. The two cases are not distinguished.
- The engine changes only
AddSuggestedpoints. The engine evaluates and deduplicates the solutions from all three supply methods, but it changes the input values only forAddSuggested. AnAddEvaluatedsolution already has a measured response for the configuration it describes, and anAddRequiredsolution is evaluated exactly as supplied, so the engine changes neither, and both come back with the caller’s values. UseAddSuggestedin this mode. - This mode is distinct from
Evaluate, which computes the expression values, constraint feasibility and objective values of one solution whose inputs and outputs the caller has already filled in.Evaluateuses the outputs rather than producing them, does not change the input values and does not deduplicate. UseSuggestedSolutionsOnlywhen you need that change of the input values and the deduplication.
Set Stop Cycles
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetStopCycles(int cycles) |
| C# | bool OptQuestModel.SetStopCycles(int cycles) |
| C++ | bool OptQuestModel::SetStopCycles(int cycles) |
| C | int OQSetStopCycles(HOptQuestModel model, int cycles) |
| Python | bool OptQuestModel.set_stop_cycles(int cycles) |
Description
Stops the optimization after cycles search cycles. The run then ends with the termination reason Auto Stop (4). A search cycle is one pass of the engine’s search methods, and the number of iterations in a cycle depends on the problem. An improvement of the best solution does not reset the count of cycles.
Set Stop Improvement
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetStopImprovement(double improvement, int iterations) |
| C# | bool OptQuestModel.SetStopImprovement(double improvement, int iterations) |
| C++ | bool OptQuestModel::SetStopImprovement(double improvement, int iterations) |
| C | int OQSetStopImprovement(HOptQuestModel model, double improvement, int iterations) |
| Python | bool OptQuestModel.set_stop_improvement(float improvement, int iterations) |
Description
Stops the optimization when iterations consecutive iterations pass without a cumulative improvement of more than the fraction improvement. The improvement is relative, measured against the best and worst feasible objective values found so far. Use a value of improvement from 0.0 to 0.2. For example, SetStopImprovement(0.01, 100) stops the run when, over the last 100 iterations, the best objective changed by 1 percent or less of the difference between the best and the worst feasible objective values. The run then ends with the termination reason Auto Stop (4). The rule applies only to a model with one objective. The engine ignores it when the model has two or more objectives.
Set Stop Time
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.SetStopTime(int seconds) |
| C# | bool OptQuestModel.SetStopTime(int seconds) |
| C++ | bool OptQuestModel::SetStopTime(int seconds) |
| C | int OQSetStopTime(HOptQuestModel model, int seconds) |
| Python | bool OptQuestModel.set_stop_time(int seconds) |
Description
Stops the optimization after seconds seconds. The current iteration completes first, so a long evaluation can make the run last longer than seconds.
Running Managed Optimization and Sampling
After the model is defined, the functions in this group run the optimization or Adaptive Sampling loop. The first call to any of them makes the model immutable (see § Concepts › Model Immutability).
In a managed run the engine owns the loop: it creates each solution, calls your evaluator, post-processes the result and reports status. The run can be serial, concurrent or asynchronous. Optimize() and Sample() take two optional callbacks: an evaluator, which is required when the model has output variables that a simulation must compute, and a monitor, which sees each completed solution, for example to update a user interface.
Sample() is the same loop as Optimize(), run by the Adaptive Sampling engine. The engine uses the metrics registered with AddSampleMetric and the method set with SetSampleMethod. Everything below about Optimize() applies to Sample() too.
Managed Optimization
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.Optimize(int nsol) throws COptQuestExceptionboolean OptQuestModel.Optimize(int nsol, IOptQuestEvaluator eval) throws COptQuestExceptionboolean OptQuestModel.Optimize(int nsol, IOptQuestEvaluator eval, IOptQuestMonitor monitor) throws COptQuestException |
| C# | bool OptQuestModel.Optimize(int nsol)bool OptQuestModel.Optimize(int nsol, IOptQuestEvaluator? eval)bool OptQuestModel.Optimize(int nsol, IOptQuestEvaluator? eval, IOptQuestMonitor? monitor) |
| C++ | bool OptQuestModel::Optimize(int nsol)bool OptQuestModel::Optimize(int nsol, const IOptQuestEvaluator& eval)bool OptQuestModel::Optimize(int nsol, const IOptQuestEvaluator& eval, const IOptQuestMonitor& monitor)bool OptQuestModel::Optimize(int nsol, const IOptQuestEvaluator* eval, const IOptQuestMonitor* monitor) |
| C | int OQOptimize(HOptQuestModel model, int nsol, OQEvaluator eval, OQMonitor monitor, void* context) |
| Python | bool OptQuestModel.optimize(int num_solutions, func evaluator=None, func monitor=None, int npar=None) |
Description
Runs a managed optimization that evaluates nsol solutions generated by the engine. There are three overloads:
Optimize(int nsol): for a model whose objectives and constraints depend only on input variables. No callback is needed.Optimize(int nsol, IOptQuestEvaluator eval): for a model with output variables that the evaluator callback computes.Optimize(int nsol, IOptQuestEvaluator eval, IOptQuestMonitor monitor): adds a monitor callback that sees each evaluated solution, for example to update a user interface.
In C++, you can pass nullptr for either callback to the overload that takes pointers. In C the callbacks are function pointers and may be NULL, and the context pointer is passed through to them. In Python the callbacks are functions that take one OptQuestSolution and may be None. Python runs the concurrent form when npar is given. A Python evaluator returns True (or any other true value, such as 1) to submit a solution, and a Python monitor returns True (or any other true value) to continue the run. A function without a return statement returns None. When an evaluator returns None, the engine rejects the trial solution, so a run with such an evaluator rejects every trial solution. When a monitor returns None, the engine stops the run after the first solution. No error text appears in either case. If a Python evaluator or monitor raises an exception, the binding stops the run, and optimize() or sample() raises the same exception after the run stops.
Returns
- Java:
truewhennsolsolutions were evaluated.falsewhen the run ended early: the monitor returnedfalse,Interruptwas called, the engine exhausted the search space, the model reached the demo limit of 50 iterations, or a stop criterion set withSetStopCycles,SetStopImprovementorSetStopTimewas met.GetTerminationReason()returns the reason. An exception thrown by the evaluator or the monitor propagates out ofOptimize. A model error throwsCOptQuestException. - C#, C++, Python:
truewhennsolsolutions were evaluated,falsewhen the run ended early (as above) or failed.GetLastError()holds the description of a failure. An empty error with afalsereturn is an early stop, not a failure. - C: non-zero when
nsolsolutions were evaluated, zero otherwise.OQGetLastError()holds the description of a failure.
Concurrent Managed Optimization
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.Optimize(int npar, int nsol) throws COptQuestExceptionboolean OptQuestModel.Optimize(int npar, int nsol, IOptQuestEvaluator eval) throws COptQuestExceptionboolean OptQuestModel.Optimize(int npar, int nsol, IOptQuestEvaluator eval, IOptQuestMonitor monitor) throws COptQuestException |
| C# | bool OptQuestModel.Optimize(int npar, int nsol)bool OptQuestModel.Optimize(int npar, int nsol, IOptQuestEvaluator? eval)bool OptQuestModel.Optimize(int npar, int nsol, IOptQuestEvaluator? eval, IOptQuestMonitor? monitor) |
| C++ | bool OptQuestModel::Optimize(int npar, int nsol)bool OptQuestModel::Optimize(int npar, int nsol, const IOptQuestEvaluator& eval)bool OptQuestModel::Optimize(int npar, int nsol, const IOptQuestEvaluator& eval, const IOptQuestMonitor& monitor)bool OptQuestModel::Optimize(int npar, int nsol, const IOptQuestEvaluator* eval, const IOptQuestMonitor* monitor) |
| C | int OQParallelOptimize(HOptQuestModel model, int npar, int nsol, OQEvaluator eval, OQMonitor monitor, void* context) |
| Python | bool OptQuestModel.optimize(int num_solutions, func evaluator=None, func monitor=None, int npar=None) |
Description
Runs a managed optimization that evaluates nsol solutions on npar threads. It behaves like Managed Optimization, but npar solutions are out for evaluation at once. The engine handles the model and the solutions in a thread-safe way. Your IOptQuestEvaluator and IOptQuestMonitor callbacks run on several threads at once, so they must synchronize any shared state of their own. The call blocks until every solution is evaluated.
In C++, you can pass nullptr for either callback to the overload that takes pointers. In C the callbacks are function pointers and may be NULL, and the context pointer is passed through to them. In Python the callbacks are functions that take one OptQuestSolution and may be None.
Returns
- As for Managed Optimization:
truewhennsolsolutions were evaluated,falseon an early stop or a failure. When one evaluator stops the run (the monitor returnedfalse, an exception, an engine error), the other evaluators finish their current solution and the call returns. The first exception raised by any evaluator is rethrown byOptimizeafter every evaluator has stopped.
Asynchronous Optimization
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.Optimize(OptQuestModelChannel ipc, int nsol) throws COptQuestExceptionboolean OptQuestModel.Optimize(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator eval) throws COptQuestExceptionboolean OptQuestModel.Optimize(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator eval, IOptQuestMonitor monitor) throws COptQuestException |
| C# | bool OptQuestModel.Optimize(OptQuestModelChannel ipc, int nsol)bool OptQuestModel.Optimize(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator? eval)bool OptQuestModel.Optimize(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator? eval, IOptQuestMonitor? monitor) |
| C++ | bool OptQuestModel::Optimize(OptQuestModelChannel& ipc, int nsol)bool OptQuestModel::Optimize(OptQuestModelChannel& ipc, int nsol, const IOptQuestEvaluator& eval)bool OptQuestModel::Optimize(OptQuestModelChannel& ipc, int nsol, const IOptQuestEvaluator& eval, const IOptQuestMonitor& monitor)bool OptQuestModel::Optimize(OptQuestModelChannel& ipc, int nsol, const IOptQuestEvaluator* eval, const IOptQuestMonitor* monitor) |
| C | int OQAsyncOptimize(HOptQuestModel model, HOptQuestModelChannel ipc, int nsol, OQEvaluator eval, OQMonitor monitor, void* context) |
Description
Runs a managed optimization that evaluates nsol solutions on the threads of the channel ipc, and lets another thread interrupt it. The call itself blocks until the run completes or is interrupted, so start it on a background thread. The main thread calls OptQuestModelChannel.Interrupt() to request early termination: the engine then generates no new solutions, and the evaluations in progress complete. The overloads are the same as those of Managed Optimization.
Returns
- As for Managed Optimization. An interrupted run returns
false, andGetTerminationReason()reportsUserStopped.
Example
// Create a channel for 5 concurrent solution evaluations
OptQuestModelChannel oqChannel = oqModel.CreateAsyncChannel(5);
// Start asynchronous optimization in a background thread
Thread background = new Thread(() -> {
try {
oqModel.Optimize(oqChannel, nsol);
} catch (COptQuestException e) {
e.printStackTrace();
}
});
background.start();
// Interrupt optimization on user event
oqChannel.Interrupt();
// Wait for graceful shutdown
background.join();Managed Adaptive Sampling
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.Sample(int nsol) throws COptQuestExceptionboolean OptQuestModel.Sample(int nsol, IOptQuestEvaluator eval) throws COptQuestExceptionboolean OptQuestModel.Sample(int nsol, IOptQuestEvaluator eval, IOptQuestMonitor monitor) throws COptQuestException |
| C# | bool OptQuestModel.Sample(int nsol)bool OptQuestModel.Sample(int nsol, IOptQuestEvaluator? eval)bool OptQuestModel.Sample(int nsol, IOptQuestEvaluator? eval, IOptQuestMonitor? monitor) |
| C++ | bool OptQuestModel::Sample(int nsol)bool OptQuestModel::Sample(int nsol, const IOptQuestEvaluator& eval)bool OptQuestModel::Sample(int nsol, const IOptQuestEvaluator& eval, const IOptQuestMonitor& monitor)bool OptQuestModel::Sample(int nsol, const IOptQuestEvaluator* eval, const IOptQuestMonitor* monitor) |
| C | int OQSample(HOptQuestModel model, int nsol, OQEvaluator eval, OQMonitor monitor, void* context) |
| Python | bool OptQuestModel.sample(int num_solutions, func evaluator=None, func monitor=None, int npar=None) |
Description
Runs managed Adaptive Sampling that evaluates nsol solutions generated by the sampling engine. The three overloads are the same as those of Managed Optimization: no callback when the metrics depend only on input variables, an evaluator when output variables must be computed, and an optional monitor. The callback conventions for C++, C and Python are the same as for Optimize.
Returns
- As for Managed Optimization.
Concurrent Managed Adaptive Sampling
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.Sample(int npar, int nsol) throws COptQuestExceptionboolean OptQuestModel.Sample(int npar, int nsol, IOptQuestEvaluator eval) throws COptQuestExceptionboolean OptQuestModel.Sample(int npar, int nsol, IOptQuestEvaluator eval, IOptQuestMonitor monitor) throws COptQuestException |
| C# | bool OptQuestModel.Sample(int npar, int nsol)bool OptQuestModel.Sample(int npar, int nsol, IOptQuestEvaluator? eval)bool OptQuestModel.Sample(int npar, int nsol, IOptQuestEvaluator? eval, IOptQuestMonitor? monitor) |
| C++ | bool OptQuestModel::Sample(int npar, int nsol)bool OptQuestModel::Sample(int npar, int nsol, const IOptQuestEvaluator& eval)bool OptQuestModel::Sample(int npar, int nsol, const IOptQuestEvaluator& eval, const IOptQuestMonitor& monitor)bool OptQuestModel::Sample(int npar, int nsol, const IOptQuestEvaluator* eval, const IOptQuestMonitor* monitor) |
| C | int OQParallelSample(HOptQuestModel model, int npar, int nsol, OQEvaluator eval, OQMonitor monitor, void* context) |
| Python | bool OptQuestModel.sample(int num_solutions, func evaluator=None, func monitor=None, int npar=None) |
Description
Runs managed Adaptive Sampling that evaluates nsol solutions on npar threads. It behaves like Concurrent Managed Optimization, including the synchronization requirement on the callbacks, and blocks until every solution is evaluated.
Returns
- As for Concurrent Managed Optimization.
Asynchronous Managed Adaptive Sampling
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.Sample(OptQuestModelChannel ipc, int nsol) throws COptQuestExceptionboolean OptQuestModel.Sample(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator eval) throws COptQuestExceptionboolean OptQuestModel.Sample(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator eval, IOptQuestMonitor monitor) throws COptQuestException |
| C# | bool OptQuestModel.Sample(OptQuestModelChannel ipc, int nsol)bool OptQuestModel.Sample(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator? eval)bool OptQuestModel.Sample(OptQuestModelChannel ipc, int nsol, IOptQuestEvaluator? eval, IOptQuestMonitor? monitor) |
| C++ | bool OptQuestModel::Sample(OptQuestModelChannel& ipc, int nsol)bool OptQuestModel::Sample(OptQuestModelChannel& ipc, int nsol, const IOptQuestEvaluator& eval)bool OptQuestModel::Sample(OptQuestModelChannel& ipc, int nsol, const IOptQuestEvaluator& eval, const IOptQuestMonitor& monitor)bool OptQuestModel::Sample(OptQuestModelChannel& ipc, int nsol, const IOptQuestEvaluator* eval, const IOptQuestMonitor* monitor) |
| C | int OQAsyncSample(HOptQuestModel model, HOptQuestModelChannel ipc, int nsol, OQEvaluator eval, OQMonitor monitor, void* context) |
Description
Runs managed Adaptive Sampling on the threads of the channel ipc, with the same interrupt mechanism and the same blocking behavior as Asynchronous Optimization.
Returns
- As for Asynchronous Optimization.
Create Asynchronous Model Channel
| Language | Function Signature |
|---|---|
| Java | OptQuestModelChannel OptQuestModel.CreateAsyncChannel(int npar) |
| C# | OptQuestModelChannel OptQuestModel.CreateAsyncChannel(int npar) |
| C++ | OptQuestModelChannel OptQuestModel::CreateAsyncChannel(int npar) |
| C | HOptQuestModelChannel OQCreateAsyncChannel(HOptQuestModel model, int npar)void OQDeleteAsyncChannel(HOptQuestModelChannel ipc) |
| Python | (no channel object; see the Notes below) |
Description
Creates an OptQuestModelChannel that links the application thread to an asynchronous run with npar parallel evaluations. Pass it to the asynchronous overloads of Optimize and Sample. In C, free the HOptQuestModelChannel handle with OQDeleteAsyncChannel when the run is over.
Returns
- Java, C#, C++: an
OptQuestModelChanneltied to the model. - C: an
HOptQuestModelChannelhandle, orNULLon failure with the description inOQGetLastError().
Notes
- Python has no channel object. Start
model.optimize(...)ormodel.sample(...)on a background thread with thenparargument, and callmodel.interrupt()on the model to stop it.model.continue_opt()clears the interrupt afterwards.
Channel Continue, Interrupt and Get Number Of Parallel
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModelChannel.Continue()void OptQuestModelChannel.Interrupt()int OptQuestModelChannel.GetNumberOfParallel() |
| C# | bool OptQuestModelChannel.Continue()void OptQuestModelChannel.Interrupt()int OptQuestModelChannel.GetNumberOfParallel() |
| C++ | bool OptQuestModelChannel::Continue()void OptQuestModelChannel::Interrupt()int OptQuestModelChannel::GetNumberOfParallel() |
| C | int OQIsAsyncContinue(HOptQuestModelChannel ipc)void OQAsyncInterrupt(HOptQuestModelChannel ipc)int OQGetNumberOfParallel(HOptQuestModelChannel ipc) |
| Python | (no channel object) |
Description
The application uses the three members of the channel to control an asynchronous run.
Continue() is a query. It reports whether the interrupt signal has been raised, so an asynchronous loop can poll it and stop cleanly. It does not resume anything. The C API uses the name OQIsAsyncContinue for the same query, to make the distinction clear. To resume an interrupted optimization, call Continue() on the model, not on the channel.
Interrupt() raises the signal on the channel and calls Interrupt() on the model. GetNumberOfParallel() returns the npar the channel was created with.
Returns
Continue: in Java, C# and C++,truewhile the run should keep generating solutions andfalseonce it is interrupted. In C, non-zero to continue and zero once interrupted.Interrupt: no return value.GetNumberOfParallel: the number of parallel evaluations the channel was created with.
Interrupt Optimization
| Language | Function Signature |
|---|---|
| Java | void OptQuestModel.Interrupt() |
| C# | void OptQuestModel.Interrupt() |
| C++ | void OptQuestModel::Interrupt() |
| C | void OQInterrupt(HOptQuestModel model) |
| Python | OptQuestModel.interrupt() -> None |
Description
Tells the model to stop generating new solutions and sets the termination reason to UserStopped. The next CreateSolution() on any thread returns an invalid solution. A managed Optimize() or Sample() that is running on another thread reaches the same invalid solution inside its loop and returns false. In a multi-threaded manual loop, every thread learns of the interrupt through its next CreateSolution() and can exit cleanly.
Returns
- No return value.
Notes
- Test the validity of every solution that
CreateSolution()returns, so that the loop ends cleanly after an interrupt. - The channel’s
Interrupt()calls this function on the model.
Continue Optimization
| Language | Function Signature |
|---|---|
| Java | void OptQuestModel.Continue() |
| C# | void OptQuestModel.Continue() |
| C++ | void OptQuestModel::Continue() |
| C | void OQContinue(HOptQuestModel model) |
| Python | OptQuestModel.continue_opt() -> None |
Description
Clears an interrupt and sets the termination reason back to Running. After Interrupt(), the model generates no new solutions until Continue() is called. Every Optimize() and Sample() calls it on entry, so a later run starts without an explicit Continue(). The channel’s Continue() is a different operation with the same name: it queries whether the interrupt signal is set. Resuming is always done through the model.
Returns
- No return value.
Manual Optimization
In manual optimization the client runs the loop. Instead of handing the engine an evaluator, the client repeatedly requests a trial solution with CreateSolution(), evaluates the inputs for this trial solution, writes the results back with SetValue, and calls Submit() or Reject() to give the outcome to the engine. The first call to CreateSolution() makes the model immutable.
Create Solution
| Language | Function Signature |
|---|---|
| Java | OptQuestSolution OptQuestModel.CreateSolution() throws COptQuestException |
| C# | OptQuestSolution OptQuestModel.CreateSolution() |
| C++ | OptQuestSolution OptQuestModel::CreateSolution() |
| C | HOptQuestSolution OQCreateSolution(HOptQuestModel model) |
| Python | OptQuestSolution OptQuestModel.create_solution() |
Description
Asks the engine for the next trial solution. The engine fills in a value for every input variable. The caller then computes the output values, writes them with SetValue and submits the solution. In C, free the HOptQuestSolution handle with OQDeleteSolution when you are done with it.
Returns
- Java, C#, C++, Python: an
OptQuestSolutiontied to the model, nevernullorNone. Always testIsValid().IsValid()returnsfalsefor one of two reasons. ReadGetTerminationReason()to tell them apart. A terminal reason means the run ended: the search space is exhausted, a stop criterion was met, or the run was interrupted.NotStartedorRunningmeans the model failed to initialize or the engine refused the request, andGetLastError()holds the message. Read the reason first, because the error message is sticky and can be left over from an earlier failure. Python raisesOptQuestErroronly when no solution object comes back at all, and Java throwsCOptQuestExceptiononly for an error inside the engine. - C: an
HOptQuestSolutionhandle. Test it withOQIsValidand readOQGetTerminationReasonthe same way.OQIsValid(NULL)is0andOQDeleteSolution(NULL)does nothing, so a NULL handle needs no separate test.
Submit Solution
| Language | Function Signature |
|---|---|
| Java | int OptQuestSolution.Submit() throws COptQuestException |
| C# | int OptQuestSolution.Submit() |
| C++ | int OptQuestSolution::Submit() |
| C | int OQSubmit(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.submit() |
Description
Gives an evaluated solution back to the engine. Set every required output value with SetValue first. Managed optimization submits solutions itself; call this only in a manual loop.
Returns
- The number of iterations the engine has completed, including this one once its last replication is submitted, or
-1on failure. The count includes the work of other threads, so it is a convenient progress measure. It is0while no iteration is complete (for example after the first replication of a trial that has more to run), so test for failure with< 0, not<= 0. Python’ssubmit()returnsFalseonly on failure.
Notes
- Call
UpdateafterSubmitto refresh the solution with the values the engine computed: objectives, constraints and expression variables.
Reject Solution
| Language | Function Signature |
|---|---|
| Java | int OptQuestSolution.Reject() throws COptQuestException |
| C# | int OptQuestSolution.Reject() |
| C++ | int OptQuestSolution::Reject() |
| C | int OQReject(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.reject() |
Description
Tells the engine that the solution could not be evaluated, for example because the simulation failed or an external condition ruled it out. The engine records the rejection and does not use the solution to guide the search. Managed optimization rejects a solution itself when the evaluator returns false; call this only in a manual loop.
Returns
- The number of iterations the engine has completed, including this one, or
-1on failure. A rejected solution counts as a completed iteration. As withSubmit,0is a success; test for failure with< 0. Python’sreject()returnsFalseonly on failure.
Notes
- Call
UpdateafterRejectif you need the solution’s state refreshed.
Predict Solution
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.Predict() throws COptQuestException |
| C# | bool OptQuestSolution.Predict() |
| C++ | bool OptQuestSolution::Predict() |
| C | int OQPredict(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.predict() |
Description
Predicts the response of a solution whose input values are set, from the engine’s current metamodel, without running the simulation. Use it to query any point in the domain.
What is predicted depends on the model. In Adaptive Sampling the metamodel is of the registered sample metrics, and the predicted values are written to each metric’s @response and @error. In an optimization there are no sample metrics, so the metamodel is of the objectives: the predicted value of each objective is written to that objective, and the uncertainty is the model’s own measurement spread, which is zero when the model runs without replications and the standard deviation across the replications when it does.
Notes
- Use it with a solution from
GetEmptySolution(),CopySolution()orCreateSolution(). Set every input value before the call. - Only the metrics (or the objectives) are predicted. Output variables are left untouched, because the engine builds no metamodel for them.
- The first
Predict()builds the metamodel; there is no separate build step. The engine rebuilds it only when the set of solutions has changed, so predicting many points against an unchanged set is cheap. - The prediction reflects every solution the model holds at the moment of the call. You can predict, collect more solutions (by sampling further or by adding evaluated solutions) and predict again, and the later prediction includes them. Predicting from inside an evaluator while a run is in progress is supported.
- The engine does not add solutions to the metamodel after the model has reached its stop criteria, because the run is finished.
- In an optimization, a metamodel of the objectives cannot be built for every model, and then
Predictreports failure rather than an unusable answer. The metamodel needs at least two decision variables, at least three evaluated feasible solutions to interpolate between, and a domain in which the distance between points is meaningful, so a model with a permutation variable or with variable bound constraints is refused. The error description gives the condition that applied. - In Adaptive Sampling,
Predictdoes not apply these checks. The call succeeds for a model with one decision variable, with fewer than three evaluated solutions, with a permutation variable or with variable bound constraints. With fewer than three evaluated solutions, the predicted response and the predicted error are both 0.GetNumberOfCompletedIterations()also counts rejected solutions, so the count can be 3 or more while the predicted values are still 0. - The JavaScript and Browser bindings do not support
Predict.
Evaluate Solution
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.Evaluate() throws COptQuestException |
| C# | bool OptQuestSolution.Evaluate() |
| C++ | bool OptQuestSolution::Evaluate() |
| C | int OQEvaluate(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.evaluate() |
Description
This is the Evaluate method of a solution. For the callback that runs your simulation in a managed run, see § Evaluate (Solution Evaluator).
Runs the model’s expressions over a solution whose input and output values the client has set. It computes every derived quantity (expression variables, constraint feasibility and objective values) and writes the results into the solution.
The solution is not given to the engine. It does not become an iteration, it is not counted among the model’s evaluated solutions, GetBestSolutions and GetAllSolutions do not return it, and it does not influence the search. Evaluate is a pure computation against the declared model: the same arithmetic the engine performs on a submitted solution, performed on demand and then discarded.
Use it in client-side tools that apply the model’s arithmetic without the search, for example a user interface in which an analyst types a scenario and sees the derived quantities update, a what-if screen that shows the scores of hand-written candidates, or a validation pass over external data.
Notes
- Use it with a solution from
GetEmptySolution()orCopySolution(). Set every value the derived quantities depend on, inputs and outputs, withSetValuebefore the call. An expression whose operands are missing cannot be computed. Evaluateis the standalone counterpart of the deferred evaluation thatSubmitperforms. Normally an expression, constraint or objective that references an output is not computed until the solution is submitted (or rejected) and refreshed withUpdate.Evaluateperforms that computation at once, with no submission and no change to the engine’s state.EvaluateandPredictanswer different questions.Predictestimates a response the client has not supplied, from a metamodel built from the solutions collected so far.Evaluatecomputes the quantities that follow exactly from the values the client has supplied. Both are available in any model.Evaluateinitializes the model if it is not initialized yet, which makes the model immutable. See § Concepts › Model Immutability.
Update Solution
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.Update() |
| C# | bool OptQuestSolution.Update() |
| C++ | bool OptQuestSolution::Update() |
| C | int OQUpdate(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.update() |
Description
Refreshes the solution with the engine’s state after Submit or Reject, so that it holds the values the engine computed, such as constraint feasibility and objective values. Managed optimization updates solutions itself; call this only in a manual loop.
Working With Solutions
An OptQuestSolution is the unit of exchange between the client and the engine. It holds a value for every input, output and expression variable of the model. From it you can also read the iteration number, the replication number, whether the solution is feasible, and whether it met its confidence requirement.
Get Empty Solution
| Language | Function Signature |
|---|---|
| Java | OptQuestSolution OptQuestModel.GetEmptySolution() throws COptQuestException |
| C# | OptQuestSolution OptQuestModel.GetEmptySolution() |
| C++ | OptQuestSolution OptQuestModel::GetEmptySolution() |
| C | HOptQuestSolution OQGetEmptySolution(HOptQuestModel model) |
| Python | OptQuestSolution OptQuestModel.get_empty_solution() |
Description
Creates an empty solution tied to the model, for the caller to fill in with SetValue. Use it with AddSuggested() (input values only), AddEvaluated() (input and output values) or AddRequired() to give the engine a solution you already know. In C, free the HOptQuestSolution handle with OQDeleteSolution when you are done with it.
Returns
- Java, C#, C++, Python: an empty
OptQuestSolutiontied to the model. - C: an
HOptQuestSolutionhandle.
Copy Solution
| Language | Function Signature |
|---|---|
| Java | OptQuestSolution OptQuestModel.CopySolution(OptQuestSolution src) throws COptQuestException |
| C# | OptQuestSolution OptQuestModel.CopySolution(OptQuestSolution src) |
| C++ | OptQuestSolution OptQuestModel::CopySolution(const OptQuestSolution& src) |
| C | HOptQuestSolution OQCopySolution(HOptQuestModel model, HOptQuestSolution src) |
| Python | OptQuestSolution OptQuestModel.copy_solution(OptQuestSolution src_solution) |
Description
Creates a new solution that belongs to this model and fills it with the values of src. src may belong to a different model. Use it to copy a solution from one model to another when you continue an optimization with changed parameters, for example after adding or tightening a constraint. Values in src whose names match variables of the destination model are copied. Other values in src are ignored, and destination variables that src does not have stay NaN. Give the copy to the engine with AddSuggested, AddEvaluated or AddRequired. In C, free the HOptQuestSolution handle with OQDeleteSolution after that.
A copy includes the values the caller set on src with SetValue and has not yet sent to the engine, as well as the values the engine holds, so a solution can be copied part-way through an evaluation. The copy has the same values as src for every variable, including every name of each special purpose variable.
Returns
- Java, C#, C++, Python: an
OptQuestSolutiontied to the destination model, filled fromsrc. - C: an
HOptQuestSolutionhandle.
Notes
- A copy is for
AddSuggested,AddEvaluatedandAddRequired. The engine did not issue it, so in C#, C++, C and Python,SubmitandRejecton a copy fail withERROR BAD SOLUTION ID(-1, orFalsein Python). The same holds for a solution fromGetEmptySolution. Java does not refuse these calls, so never callSubmitorRejecton such a solution in Java.
Add All Solutions
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestModel.AddAllSolutions(OptQuestModel src) throws COptQuestException |
| C# | bool OptQuestModel.AddAllSolutions(OptQuestModel src) |
| C++ | bool OptQuestModel::AddAllSolutions(const OptQuestModel& src) |
| C | int OQAddAllSolutions(HOptQuestModel model, HOptQuestModel src) |
| Python | bool OptQuestModel.add_all_solutions(OptQuestModel src_model) |
Description
Copies every evaluated solution of the source model src into this model. Use it to continue an optimization after you change the model, for example its constraints or objectives. Each copy is added in the same way as with AddEvaluated: the engine does not evaluate it again, and it uses its input and output values as given. The engine computes the objectives and constraints of each copy with the definitions of this model, so a copy that breaks a constraint of this model is infeasible. The engine uses the copies at the start of the next run, before it generates new solutions, and each copy counts as one of the nsol iterations of that run.
Notes
- The two models must declare the same input names and the same output names, compared without regard to case. The variable types are not compared. If the names are different, the call returns
falseand copies nothing.
Delete Solution
| Language | Function Signature |
|---|---|
| Java | Garbage Collected |
| C# | Garbage Collected |
| C++ | Destructed |
| C | void OQDeleteSolution(HOptQuestSolution sol) |
| Python | Garbage Collected |
Description
Releases the resources of an OptQuestSolution. Solutions are never constructed directly: the model creates them in CreateSolution(), GetEmptySolution(), CopySolution(), GetBestSolutions() and GetAllSolutions(). Java, C# and Python reclaim them through garbage collection. In C++ the destructor runs when the object goes out of scope. In C, call OQDeleteSolution on the handle.
Returns
- No return value.
Is Valid
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.IsValid() |
| C# | bool OptQuestSolution.IsValid()implicit operator bool(OptQuestSolution test) |
| C++ | bool OptQuestSolution::IsValid() constOptQuestSolution::operator bool() const |
| C | int OQIsValid(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.is_valid() |
Description
Reports whether the solution is valid. CreateSolution() returns an invalid solution when the engine cannot generate a new one, for example because the feasible space is exhausted, the domain is too restrictive, or the run was interrupted. In C# and C++, operator bool also converts the solution to a boolean for this test.
In C the invalid solution is a real, non-NULL handle. Test it with OQIsValid, never with handle == NULL, and release it with OQDeleteSolution like any other. A NULL handle is a separate, harder failure. OQGetLastError returns its description.
Returns
- Java, C#, C++, Python:
trueif the solution is valid,falseotherwise. - C: non-zero if valid, zero if invalid.
Notes
- An invalid solution never reaches the engine. The client refuses every engine-bound call on it and records
ERROR invalid solution:SubmitandRejectreturn-1;Predict,Evaluate,AddSuggested,AddEvaluated,AddRequiredandSetValuereturnfalse;CopySolutionof one returns another invalid solution.Updatereturnstrueand changes nothing, andGetValuereturnsNaN. - An invalid solution from an exhausted
CreateSolutionis a clean end of the run, not a failure. It leavesGetLastErroruntouched, andGetTerminationReasonreturns the reason the engine stopped.
Get Iteration
| Language | Function Signature |
|---|---|
| Java | int OptQuestSolution.GetIteration() |
| C# | int OptQuestSolution.GetIteration() |
| C++ | int OptQuestSolution::GetIteration() const |
| C | int OQGetIteration(HOptQuestSolution sol) |
| Python | int OptQuestSolution.get_iteration() |
Description
Returns the iteration number the engine assigned to the solution when it created it. All replications of one solution share the iteration number. Use it to track the sequence of solutions in a run.
Returns
- The iteration number.
Get Replication
| Language | Function Signature |
|---|---|
| Java | int OptQuestSolution.GetReplication() |
| C# | int OptQuestSolution.GetReplication() |
| C++ | int OptQuestSolution::GetReplication() const |
| C | int OQGetReplication(HOptQuestSolution sol) |
| Python | int OptQuestSolution.get_replication() |
Description
Returns the replication number of this evaluation of the solution. Each replication of a solution has its own number, which distinguishes the evaluations of one solution in a stochastic simulation.
Returns
- The replication number.
Get Number Of Completed Replications
| Language | Function Signature |
|---|---|
| Java | int OptQuestSolution.GetNumberOfCompletedReplications() |
| C# | int OptQuestSolution.GetNumberOfCompletedReplications() |
| C++ | int OptQuestSolution::GetNumberOfCompletedReplications() const |
| C | int OQGetNumberOfCompletedReplications(HOptQuestSolution sol) |
| Python | int OptQuestSolution.get_number_of_completed_replications() |
Description
Returns the number of replications that have been evaluated for the solution. For a solution from CreateSolution that you have not submitted or rejected, the number is the count of replications of the same iteration that are complete: the replication number minus 1. Without replications, it is 0.
Returns
- The number of completed replications.
Is Complete
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.IsComplete() |
| C# | bool OptQuestSolution.IsComplete() |
| C++ | bool OptQuestSolution::IsComplete() const |
| C | int OQIsComplete(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.is_complete() |
Description
Reports whether every required replication of the solution has been evaluated, so that no further evaluation is needed. This matters most in variable-replication mode. For a solution from CreateSolution that you have not submitted or rejected, it reports false.
Returns
- Java, C#, C++, Python:
trueif all replications are complete,falseotherwise. - C: non-zero if complete, zero if more replications are needed.
Is Feasible
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.IsFeasible() |
| C# | bool OptQuestSolution.IsFeasible() |
| C++ | bool OptQuestSolution::IsFeasible() const |
| C | int OQIsFeasible(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.is_feasible() |
Description
Reports whether the solution satisfies every constraint of the model.
Returns
- Java, C#, C++, Python:
trueif the solution is feasible,falseif it violates a constraint. - C: non-zero if feasible, zero if infeasible.
Has Met Confidence
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.HasMetConfidence() |
| C# | bool OptQuestSolution.HasMetConfidence() |
| C++ | bool OptQuestSolution::HasMetConfidence() const |
| C | int OQHasMetConfidence(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.has_met_confidence() |
Description
Reports whether the solution has met the confidence requirement of every objective in variable-replication mode. The result is meaningful only when confidence settings exist (see § Set Objective Confidence Parameters).
Returns
- Java, C#, C++, Python:
trueif the confidence requirements are met for every objective,falseotherwise. - C: non-zero if met, zero if any objective’s confidence is unmet.
Is Evaluated
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.IsEvaluated() |
| C# | bool OptQuestSolution.IsEvaluated() |
| C++ | bool OptQuestSolution::IsEvaluated() const |
| C | int OQIsEvaluated(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.is_evaluated() |
Description
Reports whether the solution was supplied to the engine with its output values already computed, that is, whether it was added with AddEvaluated(). A solution the engine generated, or one added with AddSuggested() or AddRequired(), reports false. An evaluated solution is not sent out for evaluation.
Returns
- Java, C#, C++, Python:
trueif the solution was added as an evaluated solution,falseotherwise. - C: non-zero if the solution was added as an evaluated solution, zero otherwise.
Get Value
| Language | Function Signature |
|---|---|
| Java | double OptQuestSolution.GetValue(String name) throws COptQuestException |
| C# | double OptQuestSolution.GetValue(string name) |
| C++ | double OptQuestSolution::GetValue(const char* name) const |
| C | double OQGetValue(HOptQuestSolution sol, const char* name) |
| Python | float OptQuestSolution.get_value(str name) |
Description
Returns the value of a named input variable, output variable, expression variable, objective or constraint. If the value is not available (the name is unknown, or the value is undefined), the result is NaN. The name can take a suffix that selects a replication, a confidence width or a part of a constraint.
Name Parameter Formats
- Basic: the name of the variable, objective or constraint, for example
"input1","objective1"or"constraint1". - Outputs with replications: by default the aggregated output value. Append
";#", where#is the replication number, for one replication, for example"output;2". - Objectives with replications: by default the aggregated objective value. Append
";#"for one replication, for example"objective;3". In variable-replication mode, append";cw"for the width of the confidence interval, for example"objective;cw". - Constraints: by default the feasibility, 1.0 for feasible and 0.0 for infeasible. For a part of the constraint expression, append:
";LHS;#": the left-hand side of the #th clause, for example"constraint1;LHS;1".";RHS;#": the right-hand side of the #th clause, for example"constraint1;RHS;1".- The clause number is 1 unless the constraint has
ORconditions, such asinput1 - input2 < 3 OR input2 + input3 > 5 - input2.
Example
For a constraint named constraint1 defined as input1 - input2 < 3 OR input2 + input3 > 5 - input2:
GetValue("constraint1")returns 1.0 if feasible and 0.0 if infeasible.GetValue("constraint1;LHS;1")returns the value ofinput1 - input2.GetValue("constraint1;RHS;1")returns 3.GetValue("constraint1;LHS;2")returns the value ofinput2 + input3.GetValue("constraint1;RHS;2")returns the value of5 - input2.
Returns
- The requested value, or
NaNif it is not available.
Set Value
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.SetValue(String name, double value) throws COptQuestException |
| C# | bool OptQuestSolution.SetValue(string name, double value) |
| C++ | bool OptQuestSolution::SetValue(const char* name, double value) |
| C | int OQSetValue(HOptQuestSolution sol, const char* name, double value) |
| Python | bool OptQuestSolution.set_value(str name, float value) |
Description
Sets the value of a named input or output variable. Its main use is to write output values during evaluation. A client can also overwrite an input value. Objectives, constraints and expression variables hold values the engine computes; a write to one of their names is discarded when the solution is sent.
Java checks the name at the call; C, C++, C# and Python check it when the solution is sent. Java returns false for a name the model does not declare. The other four keep the solution’s values in a map of their own, so the call succeeds, GetValue reads the value back, and the engine reports the name when Submit, AddSuggested, AddEvaluated or AddRequired sends the solution: ERROR BAD VALUE NAME: <name>. The engine allows objective and constraint names as an exception, so you can give a solution read back with GetBestSolutions straight back to the engine. The error for a misspelled output name therefore appears at the submit, not at the write.
Get Variable Names
| Language | Function Signature |
|---|---|
| Java | List<String> OptQuestSolution.GetInputNames() / GetOutputNames() |
| C# | List<string> OptQuestSolution.GetInputNames() / GetOutputNames() |
| C++ | int OptQuestSolution::GetInputNameCount() const / const char* OptQuestSolution::GetInputNameAt(int i) const (and Output pair) |
| C | int OQGetInputNameCount(HOptQuestSolution sol) / const char* OQGetInputNameAt(HOptQuestSolution sol, int i) (and Output pair) |
| Python | list[str] OptQuestSolution.get_input_names() / get_output_names() |
Description
Returns the names of the model’s variables in declaration order, so that a caller can loop over the values of a solution without a list of its own. The methods are on the solution rather than the model because an evaluator or monitor callback receives only a solution.
Every returned name resolves through GetValue, so the two can be looped together:
for (String name : sol.GetInputNames())
System.out.println(name + " = " + sol.GetValue(name));Most variables appear under the name they were added with. Permutations, containers and special purpose variables expand into their generated element names joined by @. Those generated names, not the base name, are what GetValue resolves:
| Declaration | Names returned |
|---|---|
AddContinuousVariable("x", 0, 10) |
x |
AddPermutationVariable("g", ["a", "b"]) |
g@a, g@b |
AddVectorVariable("v", 3, 0, 1) |
v@1, v@2, v@3 |
AddMatrixVariable("m", 2, 2, 0, 1) |
m@1,1 … m@2,2 |
AddAngleVariable("dir", 0, 360) |
dir@theta |
AddOutputVectorVariable("ovec", 2) |
ovec@1, ovec@2 (outputs) |
Inputs versus outputs
The split follows what your evaluation does with each name. GetInputNames lists every name that your evaluation reads. For a special purpose variable, that includes every name in its Notes (dir@theta, mix@compA), except the output names of a policy sequence variable.
GetInputNames: every name your evaluation reads: all standard variables, permutation members, every variable name of a container or special purpose variable except the output names listed below, and random variables. The engine writes a random variable (it draws a new value every replication), but you never supply a value for it, so it is a given that your evaluation consumes rather than a result it produces. Read it like any other input, and do not write it back when you seed a suggested solution.GetOutputNames: every name your evaluation writes: the variables added withAddOutputVariableand the elements ofAddOutputVectorVariable,AddOutputMatrixVariableandAddOutputNDVariable, the coefficient, contribution and confidence names of a policy sequence variable, which the engine computes, plus expression variables, which the engine computes and which you must not write. The engine computes an expression from your values, so it is not an input. But the engine has no marker that separates it from a simulation output, so a caller that needs “the outputs I must supply” must exclude the names it passed toAddExpressionVariableitself.
The two lists never overlap. Together they cover every name that resolves as a variable. Objectives and constraints also resolve through GetValue, but neither list reports them. Read them with the names that you gave to AddObjective and AddConstraint.
Returns
- The variable names in declaration order. An invalid solution returns an empty list (in C and C++, a count of zero).
Notes
- The base name of a container or special purpose variable is not an addressable value and is not returned.
- In C and C++, the model owns the returned pointers, and they stay valid for its lifetime. An out-of-range index returns an empty string rather than failing.
Submitting Pre-Known Solutions (Add Suggested / Add Evaluated / Add Required)
These three functions give the engine a solution the client already has. Call them before a run to use prior knowledge and speed up convergence. They differ in which values the client must set and in what happens when the solution violates the constraints:
| Method | Inputs Set By Client | Outputs Set By Client | Infeasible Handling |
|---|---|---|---|
AddSuggested |
Yes | No (OptQuest evaluates) | The engine changes the input values so that they satisfy the input-only constraints and the rules of each variable type, then evaluates the solution |
AddEvaluated |
Yes | Yes | Used as given; marked as infeasible |
AddRequired |
Yes | No (OptQuest evaluates) | Used as given; evaluated and marked as infeasible |
In all three cases:
- The client sets the values with
SetValuebefore the call. - The engine processes the supplied solutions before it generates new ones.
- Create the solution with
GetEmptySolution()orCopySolution(), so that the client can set its values directly.
Models Containing Special Purpose Variables
Set the variable names of a special purpose variable on a solution from GetEmptySolution() in the same way as any other input. The engine then handles those values as follows:
- For
AddSuggested, values of a special purpose variable that are not inside its set can change. For example, the ranks of a Sequence Variable are numbered again from 1. - For
AddEvaluatedandAddRequired, the engine uses the values as given, so supply values that are inside the set of each variable. For a policy sequence variable, the engine computes the coefficient, contribution and confidence outputs from the policy that best fits the supplied item scores.
CopySolution(src) gives a copy that has the same values as src for every variable, including every name of each special purpose variable. It is the simplest way to move solutions between two models with the same structure, and AddAllSolutions uses it.
Add Suggested
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.AddSuggested() throws COptQuestException |
| C# | bool OptQuestSolution.AddSuggested() |
| C++ | bool OptQuestSolution::AddSuggested() |
| C | int OQAddSuggested(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.add_suggested() |
Description
Submits a solution with input values only, as a warm start. Before evaluation, the engine can change the input values so that they satisfy the input-only constraints and the rules of each variable type. Use it when the inputs are a hint, not a fixed point.
Add Evaluated
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.AddEvaluated() throws COptQuestException |
| C# | bool OptQuestSolution.AddEvaluated() |
| C++ | bool OptQuestSolution::AddEvaluated() |
| C | int OQAddEvaluated(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.add_evaluated() |
Description
Submits a solution with input and output values already set. Use it to add the results of earlier simulations without evaluating them again. If the inputs violate a constraint, the engine records the solution as infeasible and does not change its input values. The engine uses the values of a special purpose variable in an evaluated solution as given.
Add Required
| Language | Function Signature |
|---|---|
| Java | boolean OptQuestSolution.AddRequired() throws COptQuestException |
| C# | bool OptQuestSolution.AddRequired() |
| C++ | bool OptQuestSolution::AddRequired() |
| C | int OQAddRequired(HOptQuestSolution sol) |
| Python | bool OptQuestSolution.add_required() |
Description
Submits a solution with input values only, like AddSuggested, but the engine evaluates the inputs as supplied and does not change them. If the inputs violate a constraint, the engine evaluates the solution and marks it infeasible. The engine uses the values of a special purpose variable in a required solution as given, and the simulator receives them as given. Use it when the supplied inputs must be honored exactly.
Retrieving Results
Get Best Solutions
| Language | Function Signature |
|---|---|
| Java | List<OptQuestSolution> OptQuestModel.GetBestSolutions()List<OptQuestSolution> OptQuestModel.GetBestSolutions(int limit) |
| C# | List<OptQuestSolution> OptQuestModel.GetBestSolutions(int limit = 1) |
| C++ | int OptQuestModel::GetBestSolutions(int limit = 1)const OptQuestSolution& OptQuestModel::GetBestSolutionsAt(int i) |
| C | int OQGetBestSolutions(HOptQuestModel model, int limit)HOptQuestSolution OQGetBestSolutionsAt(HOptQuestModel model, int i) |
| Python | list[OptQuestSolution] OptQuestModel.get_best_solutions(int limit=1) |
Description
Returns the best solutions found so far. Java, C# and Python return a list; C++ and C return a count and give access by index. The result is a list even when it holds one solution. The list is empty when the model has no completed iterations, for example before the first run or after a failed initialization, so test its length before you read the first entry. The first entry can be infeasible when the run found no feasible solution, so test IsFeasible() on it.
For a single objective, the order is:
- The feasible solutions, by objective value.
- The infeasible solutions, by objective value. The order does not depend on the size of a constraint violation, so when no solution is feasible, the first entry is the infeasible solution with the best objective value. An infeasible solution whose objective is
NaN, for example because the evaluator did not set an output that the objective uses, comes after the infeasible solutions whose objective is a number, for a minimized and for a maximized objective. - The solutions that the evaluator rejected. Their objective is
NaN.
Solutions with equal objective values are in iteration order. For several objectives, the Pareto frontier is in no particular order.
GetBestSolutions(): for a single objective, the single best solution. For several objectives, every solution on the Pareto frontier.GetBestSolutions(int limit): for several objectives, every solution on the Pareto frontier regardless oflimit. For a single objective,limithas three modes:limit > 0: the bestlimitsolutions, best first.limit == 0: every evaluated solution, best first.limit < 0: the worst|limit|solutions, worst first, which is useful for diagnostics.
In C and C++, GetBestSolutions returns the number of solutions, and GetBestSolutionsAt(int i) returns each one. The result list is per-model state: a later GetBestSolutions (or GetAllSolutions) on the same model replaces it, so an index that referred to one solution can refer to another afterwards. Fetch the count and read the entries out before you fetch again, and use the model’s result list from one thread at a time. In C, each OQGetBestSolutionsAt call is a fresh allocation that the caller owns and must release with OQDeleteSolution; a handle already fetched keeps its values across a later fetch. In C++, GetBestSolutionsAt returns a reference to an entry of the result list. That reference is not valid after the next fetch. To keep a solution, copy it: OptQuestSolution best(model.GetBestSolutionsAt(0));. In Java and C#, GetBestSolutions returns a new List each call. In Python, the binding makes per-call copies, and each returned OptQuestSolution owns its handle.
An index at or beyond the count, and a negative index, return a real, non-NULL handle whose OQIsValid is 0 and whose OQGetValue is NaN. Check the index against the count, or check OQIsValid; a NULL test does not detect it. That handle is an allocation too, so delete it.
Returns
- Java, C#, Python: a
ListofOptQuestSolutionobjects. - C++, C:
GetBestSolutionsreturns the number of solutions, andGetBestSolutionsAtreturns the solution at indexi.
Get All Solutions
| Language | Function Signature |
|---|---|
| Java | List<OptQuestSolution> OptQuestModel.GetAllSolutions() throws COptQuestException |
| C# | List<OptQuestSolution> OptQuestModel.GetAllSolutions() |
| C++ | int OptQuestModel::GetAllSolutions()const OptQuestSolution& OptQuestModel::GetAllSolutionsAt(int i) |
| C | int OQGetAllSolutions(HOptQuestModel model)HOptQuestSolution OQGetAllSolutionsAt(HOptQuestModel model, int i) |
| Python | list[OptQuestSolution] OptQuestModel.get_all_solutions() |
Description
Returns every evaluated solution: feasible, infeasible and rejected. Java, C# and Python return a list; C++ and C return a count and give access by index.
In C and C++, GetAllSolutions returns the number of solutions, and GetAllSolutionsAt(int i) returns each one. The result list is per-model state, and an out-of-range index returns the invalid-solution handle, the same as for GetBestSolutions.
Returns
- Java, C#, Python: a
ListofOptQuestSolutionobjects. - C++, C:
GetAllSolutionsreturns the number of solutions, andGetAllSolutionsAtreturns the solution at indexi.
Get Number Of Completed Iterations
| Language | Function Signature |
|---|---|
| Java | int OptQuestModel.GetNumberOfCompletedIterations() |
| C# | int OptQuestModel.GetNumberOfCompletedIterations() |
| C++ | int OptQuestModel::GetNumberOfCompletedIterations() |
| C | int OQGetNumberOfCompletedIterations(HOptQuestModel model) |
| Python | int OptQuestModel.get_number_of_completed_iterations() |
Description
Returns the number of solutions that have been evaluated: feasible, infeasible and rejected alike. In a concurrent run this is the count across every evaluator thread, so it is a convenient progress indicator for a monitor callback.
Returns
- The number of evaluated solutions, or
0if the model is not initialized.
Get Max Replications
| Language | Function Signature |
|---|---|
| Java | int OptQuestModel.GetMaxReplications() |
| C# | int OptQuestModel.GetMaxReplications() |
| C++ | int OptQuestModel::GetMaxReplications() |
| C | int OQGetMaxReplications(HOptQuestModel model) |
| Python | int OptQuestModel.get_max_replications() |
Description
Returns the maximum replication count set with SetReplications. It is the upper bound of the replication numbers that GetReplication() can report, so use it as the loop bound when you read per-replication values from a solution with the "<name>;<replication>" form of GetValue.
Returns
- The maximum replication count, or
0if the model is not initialized or replications were never set.
Get Termination Reason
| Language | Function Signature |
|---|---|
| Java | int OptQuestModel.GetTerminationReason() |
| C# | int OptQuestModel.GetTerminationReason() |
| C++ | int OptQuestModel::GetTerminationReason() |
| C | int OQGetTerminationReason(HOptQuestModel model) |
| Python | int OptQuestModel.get_termination_reason() |
Description
Returns why the last run stopped, as one of the constants below.
Returns
| Reason | Java, C# | C++ | C, Python | Meaning |
|---|---|---|---|---|
Not Started = 0 |
OptQuestModel.TerminationReason.NotStarted |
OptQuestModel::TerminationReason::NotStarted |
OQTerminationReasonNotStarted |
No run has started. |
Running = 1 |
OptQuestModel.TerminationReason.Running |
OptQuestModel::TerminationReason::Running |
OQTerminationReasonRunning |
A run is in progress, or Continue() cleared an interrupt. |
LP Solved = 3 |
OptQuestModel.TerminationReason.LP |
OptQuestModel::TerminationReason::LP |
OQTerminationReasonLP |
The objective and every constraint are linear, and the engine solved the problem exactly. |
Auto Stop = 4 |
OptQuestModel.TerminationReason.AutoStop |
OptQuestModel::TerminationReason::AutoStop |
OQTerminationReasonAutoStop |
The engine stopped the run because of a stop rule set with SetStopCycles or SetStopImprovement. |
Optimal Found = 5 |
OptQuestModel.TerminationReason.OptimalFound |
OptQuestModel::TerminationReason::OptimalFound |
OQTerminationReasonOptimalFound |
The engine has no other candidate to try, for example because it evaluated every combination of values or because the constraints fix the values. |
Max Iterations = 6 |
OptQuestModel.TerminationReason.MaxIterations |
OptQuestModel::TerminationReason::MaxIterations |
OQTerminationReasonMaxIterations |
The run completed the number of iterations that you asked for. |
Max Time = 7 |
OptQuestModel.TerminationReason.MaxTime |
OptQuestModel::TerminationReason::MaxTime |
OQTerminationReasonMaxTime |
The engine stopped the run because it reached the time set with SetStopTime. |
User Stopped = 8 |
OptQuestModel.TerminationReason.UserStopped |
OptQuestModel::TerminationReason::UserStopped |
OQTerminationReasonUserStopped |
The run was stopped, for example by Interrupt() or by a monitor that returned false. |
Best Found = 9 |
OptQuestModel.TerminationReason.BestFound |
OptQuestModel::TerminationReason::BestFound |
OQTerminationReasonBestFound |
Not used. The engine does not set this reason. |
Exception = 10 |
OptQuestModel.TerminationReason.Exception |
OptQuestModel::TerminationReason::Exception |
OQTerminationReasonException |
The run stopped because of an error. Read the error text. |
Factories Done = 11 |
OptQuestModel.TerminationReason.FactoriesDone |
OptQuestModel::TerminationReason::FactoriesDone |
OQTerminationReasonFactoriesDone |
The engine has no more solutions to generate. With SuggestedSolutionsOnly, the supplied solutions are used up. |
Infeasible = 12 |
OptQuestModel.TerminationReason.Infeasible |
OptQuestModel::TerminationReason::Infeasible |
OQTerminationReasonInfeasible |
No input values satisfy the constraints. |
Cannot Generate = 13 |
OptQuestModel.TerminationReason.CannotGenerate |
OptQuestModel::TerminationReason::CannotGenerate |
OQTerminationReasonCannotGenerate |
The engine cannot generate a solution that is different from the solutions it already has. |
Max Demo Iterations = 14 |
OptQuestModel.TerminationReason.MaxDemoIterations |
OptQuestModel::TerminationReason::MaxDemoIterations |
OQTerminationReasonMaxDemoIterations |
No license is set, and the run stopped at 50 iterations. Call SetLicense. |
Set Termination Reason
| Language | Function Signature |
|---|---|
| Java | void OptQuestModel.SetTerminationReason(int reason) |
| C# | void OptQuestModel.SetTerminationReason(int reason) |
| C++ | void OptQuestModel::SetTerminationReason(int reason) |
| C | void OQSetTerminationReason(HOptQuestModel model, int reason) |
| Python | OptQuestModel.set_termination_reason(int reason) -> None |
Description
Overrides the model’s termination reason with one of the constants listed under Get Termination Reason. It exists for OptTek’s own use and for the bindings’ Interrupt() and Continue() implementations. Applications call Interrupt() and Continue() instead.
Returns
- No return value.
Managed Optimization Callbacks
With the callbacks, the client runs its own code inside the managed Optimize() and Sample() loops. The evaluator computes the output values of each trial solution. The optional monitor sees each completed solution and can stop the run.
Evaluate (Solution Evaluator)
| Language | Function Signature |
|---|---|
| Java | boolean IOptQuestEvaluator.Evaluate(OptQuestSolution sol) |
| C# | bool IOptQuestEvaluator.Evaluate(OptQuestSolution sol) |
| C++ | bool IOptQuestEvaluator::operator()(OptQuestSolution& sol) const |
| C | typedef int (*OQEvaluator)(HOptQuestSolution sol, void* context) |
| Python | def evaluate(sol) -> bool |
Description
This is the callback that runs your simulation in a managed run. For the Evaluate method of a solution, which computes the expressions, constraints and objectives of values that you supply, see § Evaluate Solution.
The evaluator is an object that implements IOptQuestEvaluator in Java, C# or C++, a function that takes a solution in Python, or a function pointer of type OQEvaluator in C. The engine calls it to evaluate each OptQuestSolution during a managed run. For a stochastic model with replications, the engine calls it once per replication of each trial. Across the replications of one trial the decision-variable values are identical, and the random variables (declared with Add*RandomVariable) are drawn again for each call.
- Input: the solution
solarrives with its input values set. Read them withGetValue().sol.GetIteration()identifies the trial, andsol.GetReplication()identifies the replication. - Evaluate: the callback runs the simulation or other computation and writes the output values with
SetValue(). - Result: when the callback returns
true, the engine submits the solution (the equivalent ofSubmit()). When it returnsfalse, the engine rejects the solution (the equivalent ofReject()). In Python, end the evaluator withreturn True(any other true value, such as 1, also submits). A function without areturnstatement returnsNone, and the engine rejects the solution with no error text.
In C, the context argument of Optimize is passed to the callback. In a concurrent or asynchronous run the engine calls the evaluator on several threads at once, so the callback must synchronize any shared state that the engine does not manage.
Example
class MyEvaluator implements IOptQuestEvaluator {
public boolean Evaluate(OptQuestSolution sol) {
try {
double x = sol.GetValue("x");
double y = runSimulation(x); // your code
sol.SetValue("y", y);
return true; // false rejects the solution
} catch (COptQuestException e) {
return false;
}
}
}
model.Optimize(100, new MyEvaluator());In Java, GetValue and SetValue declare throws COptQuestException, and Evaluate does not, so the evaluator catches the exception.
Returns
- Java, C#, C++, Python:
trueto submit the solution,falseto reject it. - C: non-zero to submit, zero to reject.
Monitor (Solution Monitor)
| Language | Function Signature |
|---|---|
| Java | boolean IOptQuestMonitor.Monitor(OptQuestSolution sol) |
| C# | bool IOptQuestMonitor.Monitor(OptQuestSolution sol) |
| C++ | bool IOptQuestMonitor::operator()(OptQuestSolution& sol) const |
| C | typedef int (*OQMonitor)(HOptQuestSolution sol, void* context) |
| Python | def monitor(sol) -> bool |
Description
The monitor is an object that implements IOptQuestMonitor in Java, C# or C++, a function that takes a solution in Python, or a function pointer of type OQMonitor in C. The engine calls it after it has post-processed an evaluated solution. The engine calls it as often as the evaluator: for a stochastic model with replications, the monitor runs once per replication of each trial, after the evaluator returns and the engine finishes its bookkeeping for that replication.
- Input: the solution
solarrives with its input values, output values, constraints and objectives. Read them withGetValue(). - Examine: the callback updates application state, such as a user interface, or tests an early-stop condition on the solution’s results.
- Result: when the callback returns
true, the engine continues. When it returnsfalse, the engine stops generating solutions and the run ends early. In Python, a monitor that returnsNonestops the run. In a concurrent run the evaluations in progress complete, but no new solutions are generated.
In C, the context argument is passed to the callback. In a concurrent run the engine calls the monitor on several threads at once, so the callback must synchronize any shared state that the engine does not manage.
Example
class StopAtTarget implements IOptQuestMonitor {
public boolean Monitor(OptQuestSolution sol) {
try {
double profit = sol.GetValue("profit");
System.out.println("iteration " + sol.GetIteration() + ": " + profit);
return profit < 1000; // false stops the run
} catch (COptQuestException e) {
return false;
}
}
}
model.Optimize(100, new MyEvaluator(), new StopAtTarget());With replications, the engine calls the monitor once for each replication. In the monitor, GetValue on an output or an objective gives the combined value of the replications that are complete so far. To stop on the combined value of all the replications of a trial solution, test IsComplete() before you compare the value, for example return !sol.IsComplete() || profit < 1000;.
Returns
- Java, C#, C++, Python:
trueto continue,falseto stop generating new solutions. - C: non-zero to continue, zero to stop.
Utility Functions
Get Last Error (Model)
| Language | Function Signature |
|---|---|
| Java | Java reports errors by throwing COptQuestException. |
| C# | string OptQuestModel.GetLastError() |
| C++ | const char* OptQuestModel::GetLastError() const |
| C | const char* OQGetLastError(HOptQuestModel model) |
| Python | str OptQuestModel.get_last_error() |
Description
Returns the description of the last error recorded on the model. Read it after a model function returns false (0 in C). Java has no such method; it throws COptQuestException instead. The text is sticky and per-thread; see § Concepts › Error Handling.
Returns
- The last error message and the relevant call stack.
Get Last Error (Solution)
| Language | Function Signature |
|---|---|
| Java | Java reports errors by throwing COptQuestException. |
| C# | string OptQuestSolution.GetLastError() |
| C++ | const char* OptQuestSolution::GetLastError() const |
| C | const char* OQGetLastSolutionError(HOptQuestSolution sol) |
| Python | str OptQuestSolution.get_last_error() |
Description
Returns the description of the last error recorded on the solution. Read it after a solution method returns false (0 in C), or after Submit or Reject returns -1.
Returns
- The last error message and the relevant call stack.
Get Version Info
| Language | Function Signature |
|---|---|
| Java | static String OptQuest.GetVersionInfo() |
| C# | static string OptQuestNet.GetVersionInfo() |
| C++ | static const char* OptQuest::GetVersionInfo() |
| C | const char* OQGetVersionInfo() |
| Python | str get_version_info() |
Description
Returns a string that identifies the version of the engine library that is loaded.
Returns
- The version string.
Reference
This chapter holds the reference material behind the API: the expression language, the probability distributions that Response Distribution Sampling uses, the steps to link OptQuest into a project in each language, and the STDIO interface for environments that cannot link OptQuest directly.
Functions and Constants Available In Expressions
These functions and constants are available in the expressions of objectives, constraints, sample metrics and expression variables. They are grouped by category. Function names are case-insensitive. The arithmetic operators are +, -, *, / and ^ for a power; ** is accepted as a synonym for ^.
Constants
| Constant | Description |
|---|---|
pi |
Mathematical constant π, approximately equal to 3.14159. |
e |
Mathematical constant e, approximately equal to 2.71828. |
Variable Argument Functions and Arrays
A function marked variadic accepts any number of arguments as a comma-separated list, for example min(a, b), min(a, b, c) or sum(x1, x2, x3, x4). The same functions also accept one or more array(...) groups, and arrays can be mixed with standard variables or nested: sum(array(x, y), z) and max(array(1, 2, 3), 0.5) are both valid. array(...) exists only to pass a group of values into a variable argument function. It has no meaning on its own.
Arithmetic, Powers, and Logarithms
| Function | Description |
|---|---|
abs(x) |
Returns the absolute value of a number. |
signum(x) |
Returns -1 if x < 0, 1 if x > 0, otherwise 0. |
sqrt(x) |
Returns the square root of a number. |
cbrt(x) |
Returns the cube root of a number (defined for negative x). |
pow(x,y) |
Returns x raised to the power y. |
exp(x) |
Returns e raised to the power x. |
expm1(x) |
Returns exp(x) - 1, accurate even when x is close to 0. |
log(x) |
Returns the natural logarithm (base e) of a number. |
log10(x) |
Returns the base-10 logarithm of a number. |
log2(x) |
Returns the base-2 logarithm of a number. |
log1p(x) |
Returns log(1 + x), accurate even when x is close to 0. |
logbase(b,x) |
Returns the logarithm of x in base b, that is, log(x) / log(b). |
Rounding and Remainders
| Function | Description |
|---|---|
floor(x) |
Returns the largest whole number less than or equal to x. |
ceil(x) |
Returns the smallest whole number greater than or equal to x. |
round(x) |
Returns the nearest whole number; ties are rounded away from zero (round(2.5) is 3, round(-2.5) is -3). |
trunc(x) |
Returns the integer part of x, truncated toward zero. |
frac(x) |
Returns the fractional part of x toward zero, that is, x - trunc(x) (frac(-2.7) is -0.7). |
mod(x,y) |
Returns the modulo of x by y, taking the sign of y (mod(-5,3) is 1). |
fmod(x,y) |
Returns the IEEE remainder of x / y (may be negative). |
Trigonometry and Angle Conversion
| Function | Description |
|---|---|
sin(x) |
Returns the sine of x, where x is an angle in radians. |
cos(x) |
Returns the cosine of x, where x is an angle in radians. |
tan(x) |
Returns the tangent of x, where x is an angle in radians. |
asin(x) |
Returns the arcsine of x, in radians. |
acos(x) |
Returns the arccosine of x, in radians. |
atan(x) |
Returns the arctangent of x, in radians. |
atan2(y,x) |
Returns the arctangent of y/x in the range −π to π radians, using the signs of both arguments to place the result in the correct quadrant. The first argument is y, matching C, Java and Python: atan2(1, 2) is 0.4636…, not 1.1071…. If both parameters are 0, returns 0. |
dtor(x) |
Converts degrees to radians. |
rtod(x) |
Converts radians to degrees. |
Hyperbolic Functions
| Function | Description |
|---|---|
sinh(x) |
Returns the hyperbolic sine of x. |
cosh(x) |
Returns the hyperbolic cosine of x. |
tanh(x) |
Returns the hyperbolic tangent of x. |
asinh(x) |
Returns the inverse hyperbolic sine of x (defined for all real x). |
acosh(x) |
Returns the inverse hyperbolic cosine of x; NaN for x < 1. |
atanh(x) |
Returns the inverse hyperbolic tangent of x, defined on (-1, 1); ±Inf at ±1. |
Comparison, Logic, and Conditionals
| Function | Description |
|---|---|
eq(x,y) |
Returns 1 if x == y, otherwise 0. |
ne(x,y) |
Returns 1 if x != y, otherwise 0. |
lt(x,y) |
Returns 1 if x < y, otherwise 0. |
le(x,y) |
Returns 1 if x <= y, otherwise 0. |
gt(x,y) |
Returns 1 if x > y, otherwise 0. |
ge(x,y) |
Returns 1 if x >= y, otherwise 0. |
and(...) |
Variadic. Returns 1 if every argument is nonzero, otherwise 0 (NaN if any argument is non-finite). |
or(...) |
Variadic. Returns 1 if any argument is nonzero, otherwise 0 (NaN if any argument is non-finite). |
not(x) |
Returns 1 if x == 0, otherwise 0. |
xor(x,y) |
Returns 1 if exactly one of x, y is nonzero, otherwise 0. |
between(x,lo,hi) |
Returns 1 if lo <= x <= hi, otherwise 0. |
finite(x) |
Returns 1 if x is a finite IEEE floating-point number (not NaN or Inf), otherwise 0. |
ifnan(x,fallback) |
Returns x if x is finite, otherwise fallback. Useful for keeping an objective finite. |
if(x,y,z) |
Returns y if x != 0, otherwise z. |
choose(i,a,b,...) |
Variadic. Returns the i-th argument, 1-based (choose(2,a,b,c) is b); NaN if i is out of range. |
indexof(value,x1,...) |
Variadic. Returns the 1-based position of the first argument exactly equal to value; NaN if none match. |
Clamping, Interpolation, and Smoothing
These functions shape objectives and constraints. The smooth variants (softplus, sigmoid, smoothmax, smoothmin) are differentiable everywhere; the hard forms (clamp, relu) are not.
| Function | Description |
|---|---|
clamp(x,lo,hi) |
Returns lo if x < lo, hi if x > hi, otherwise x. |
lerp(a,b,t) |
Linear interpolation between a and b: a + t * (b - a). |
relu(x) |
Returns max(0, x). |
pos(x) |
Alias for relu(x); returns max(0, x). |
negpart(x) |
Returns max(0, -x), the magnitude of the negative part of x. |
softplus(x) |
Returns log(1 + exp(x)), a smooth approximation to relu. |
sigmoid(x) |
Returns 1 / (1 + exp(-x)), the logistic function. |
logit(x) |
Returns log(x / (1 - x)), the inverse of sigmoid. |
smoothmax(k,x1,x2,...) |
Variadic. A smooth, differentiable approximation to the maximum that sharpens as k increases (k > 0). |
smoothmin(k,x1,x2,...) |
Variadic. A smooth, differentiable approximation to the minimum (k > 0). |
Aggregation Over a List
All of these are variadic. They accept a comma-separated list or one or more array(...) groups (see § Variable Argument Functions and Arrays above).
| Function | Description |
|---|---|
sum(...) |
Returns the sum of the values. |
average(...) |
Returns the arithmetic mean of the values. |
product(...) |
Returns the product of the values, accumulated in log space to resist overflow and underflow. |
geomean(...) |
Returns the geometric mean of the values; NaN if any value is <= 0. |
min(...) |
Returns the smallest value. Accepts both min(a, b) and min(array(...)). |
max(...) |
Returns the largest value. Accepts both max(a, b) and max(array(...)). |
median(...) |
Returns the median of the values. |
range(...) |
Returns the spread of the values, max - min. |
count(...) |
Returns the number of values. |
variance(...) |
Returns the population variance (divides by n). |
stdev(...) |
Returns the population standard deviation (divides by n). |
percentile(p,x1,x2,...) |
Returns the p-th percentile of the values by linear interpolation, with p in [0, 1] given as the first argument. |
norm(...) |
Returns the Euclidean (L2) norm, sqrt(sum(xi^2)). |
norm1(...) |
Returns the L1 norm, sum(abs(xi)). |
norminf(...) |
Returns the L∞ norm, max(abs(xi)). |
logsumexp(...) |
Returns log(sum(exp(xi))), computed in a numerically stable way. |
argmax(...) |
Returns the 1-based position of the largest value (the first one on ties). |
argmin(...) |
Returns the 1-based position of the smallest value (the first one on ties). |
sumproduct(array(...),array(...)) |
Returns the sum of the elementwise products of two or more equal-length arrays. |
array(...) |
Groups values into a single array argument for the variable argument functions above; not used on its own. |
Distance and Geometry
| Function | Description |
|---|---|
hypot(x,y) |
Returns sqrt(x^2 + y^2) without intermediate overflow. |
dist(x1,y1,x2,y2) |
Returns the Euclidean distance between the points (x1, y1) and (x2, y2). |
sphdist(lat1,lon1,lat2,lon2) |
Returns the great-circle (haversine) distance between two points on a unit sphere (radius 1), in radians. Latitude and longitude are also given in radians; convert from degrees with dtor. Multiply the result by a radius to get a distance in the units you want (for example 6371 for kilometers on Earth, or 3958.8 for miles). |
geodist(lat1,lon1,lat2,lon2) |
Returns the great-circle (haversine) distance between two points on Earth in kilometers, assuming a spherical earth of radius 6371 km. Latitude and longitude are given in degrees. Equivalent to 6371 * sphdist(dtor(lat1), dtor(lon1), dtor(lat2), dtor(lon2)). |
Combinatorics and Special Functions
| Function | Description |
|---|---|
factorial(x) |
Returns x! for whole x >= 0 (x is truncated to an integer). |
combin(n,k) |
Returns the number of combinations of n items taken k at a time (n choose k). |
permut(n,k) |
Returns the number of permutations of n items taken k at a time, n! / (n - k)!. |
erf(x) |
Returns the Gauss error function of x. |
erfc(x) |
Returns the complementary error function, 1 - erf(x). |
lgamma(x) |
Returns the natural logarithm of the absolute value of the gamma function of x. |
gammaln(x) |
Alias for lgamma(x). |
sinc(x) |
Returns the unnormalized sinc function, sin(x) / x, with sinc(0) defined as 1. |
Financial
The financial functions follow the spreadsheet sign convention: cash you receive is positive, cash you pay is negative, and payments occur at the end of each period. The argument order differs between the functions: the quantity a function solves for is the one that is missing from its arguments.
| Function | Description |
|---|---|
npv(rate,cf1,cf2,...) |
Variadic. Returns the net present value of a series of cash flows at the given rate; the first cash flow is discounted one period. |
irr(cf0,cf1,...) |
Variadic. Returns the internal rate of return (the rate at which the net present value is zero); cf0 occurs at time 0. |
pmt(rate,nper,pv,fv) |
Returns the payment per period for a loan or annuity. |
fv(rate,nper,pmt,pv) |
Returns the future value. |
pv(rate,nper,pmt,fv) |
Returns the present value. |
nper(rate,pmt,pv,fv) |
Returns the number of periods. |
rate(nper,pmt,pv,fv) |
Returns the interest rate per period. |
Random Sampling and Inverse CDF (PPF)
| Function | Description |
|---|---|
rand() |
Returns a uniformly distributed random number in [0, 1). |
betappf(p,alpha,beta) |
Returns the percent point function* of the Beta distribution of p with parameters alpha and beta using the same conventions as scipy.stats.beta. |
cauchyppf(p,location,scale) |
Returns the percent point function* of the Cauchy distribution of p with parameters location and scale using the same conventions as scipy.stats.cauchy. |
chisqppf(p,df) |
Returns the percent point function* of the Chi-squared distribution of p with parameter df using the same conventions as scipy.stats.chi2. |
expppf(p,scale) |
Returns the percent point function* of the Exponential distribution of p with parameter scale using the same conventions as scipy.stats.expon. |
gammappf(p,a,scale) |
Returns the percent point function* of the Gamma distribution of p with parameters a and scale using the same conventions as scipy.stats.gamma. |
lognormppf(p,shape,scale) |
Returns the percent point function* of the Log Normal distribution of p with parameters shape and scale using the same conventions as scipy.stats.lognorm. |
normppf(p,mean,sigma) |
Returns the percent point function* of the Normal distribution of p with parameters mean and sigma using the same conventions as scipy.stats.norm. |
paretoppf(p,gamma,location,scale) |
Returns the percent point function* of the Pareto distribution of p with parameters gamma, location, and scale using the same conventions as scipy.stats.pareto. |
poissonppf(p,lambda) |
Returns the percent point function* of the Poisson distribution of p with parameter lambda using the same conventions as scipy.stats.poisson. |
tppf(p,df) |
Returns the percent point function* of the T distribution of p with parameter df using the same conventions as scipy.stats.t. |
uniformppf(p,min,max) |
Returns the percent point function* of the Uniform distribution of p from min to max using the same conventions as scipy.stats.uniform. |
weibullppf(p,shape,scale) |
Returns the percent point function* of the Weibull distribution of p with parameters shape and scale using the same conventions as scipy.stats.weibull_min. |
* The percent point function (PPF), also called the inverse cumulative distribution function, returns the value x such that the probability of a draw at or below x is p. For a CDF F(x) = P(X <= x), the PPF is F^(-1)(p) = x, with p in [0, 1]. Its usual use is to draw random numbers from a distribution: betappf(rand(), alpha, beta) turns a uniform random number into a draw from Beta(alpha, beta).
Probability Distributions
Response Distribution Sampling (RDS) is a special case of Adaptive Sampling. The engine tracks two things: the current empirical distribution of the responses from the simulation, that is, what is known now, and the predicted distribution of the responses at the candidate points, estimated from the surrogate model. The next point to evaluate is the one that is predicted to move the empirical distribution closest to the wanted distribution.
The method is a discretized form of inverse transform sampling. The engine uses the wanted distribution to build bins of unequal width for the histogram of the empirical distribution. The bins are placed so that, if the empirical distribution matched the wanted one, every bin would hold the same number of samples. The response values that must be sampled next are therefore the values of a bin with too few samples. There is no need for a histogram of equal bins and a statistical test of which bin moves the empirical distribution most; a count per bin is sufficient.
The engine builds the bins for the common distributions listed below. For any other distribution, supply the bin edges yourself with SetSampleRDSDiscrete. Texts differ on the definitions of some of these distributions. OptQuest uses the definitions of the Python scipy.stats package.
Uniform
A uniform continuous random variable on [a, b]. Every value from a to b is equally likely.
\text{uniform}(a, b)
a: Lower bound
b: Upper bound
\text{PDF}(x) = \begin{cases} \frac{1}{b - a} & a \leq x < b \\ 0 & \text{otherwise} \end{cases}
Normal
A normal continuous random variable with mean \mu and standard deviation \sigma. The values spread symmetrically around \mu. About 95 percent of the values are within 2\sigma of \mu.
\text{norm}(\mu, \sigma)
\mu: Mean
\sigma: Standard deviation
\text{PDF}(x) = \frac{1}{\sigma \sqrt{2\pi}} \exp\left( -\frac{(x - \mu)^2}{2\sigma^2} \right)
Log Normal
A lognormal continuous random variable: a value whose logarithm has a normal distribution. \text{scale} is the median.
\text{lognorm}(s, \text{scale})
s: Shape parameter
\text{scale}: Scale parameter
\text{PDF}(x) = \frac{1}{s x \sqrt{2\pi}} \exp\left( -\frac{(\ln (x / \text{scale}))^2}{2 s^2} \right)
Beta
A beta continuous random variable: a value from 0 to 1, such as a proportion. The two shape parameters set where the values collect. With \alpha = \beta = 1, every value from 0 to 1 is equally likely. The mean is \alpha / (\alpha + \beta).
\mathrm{Beta}(\alpha,\beta)
\alpha: Shape parameter
\beta: Shape parameter
\text{PDF}(x) = \frac{x^{\alpha-1} (1-x)^{\beta-1}}{B(\alpha, \beta)}
Poisson
A Poisson discrete random variable: the number of events in a fixed interval, when the events occur at random at an average rate of \lambda for each interval. The mean is \lambda.
\text{poisson}(\lambda)
\lambda: Rate parameter
\text{PMF}(k) = e^{-\lambda} \frac{\lambda^k}{k!}
Exponential
An exponential continuous random variable: the time between events that occur at random at a constant average rate. \text{scale} is the mean time.
\text{exponential}(\text{scale})
\text{scale}: Scale parameter
\text{PDF}(x) = \frac{1}{\text{scale}} \exp\left( -\frac{x}{\text{scale}} \right)
Cauchy
A Cauchy continuous random variable. The values spread symmetrically around \text{location}, which is the median. Values far from the median are much more likely than with a normal distribution, and the distribution has no mean.
\text{cauchy}(\text{location}, \text{scale})
\text{location}: Location parameter
\text{scale}: Scale parameter
\text{PDF}(x) = \frac{1}{\pi \text{scale} \left[1 + \left( \frac{x - \text{location}}{\text{scale}} \right)^2 \right]}
Gamma
A gamma continuous random variable: a positive value. For a whole number a, it is the total time of a steps that each take an exponential time with the mean \text{scale}. The mean is a \cdot \text{scale}.
\text{gamma}(a, \text{scale})
a: Shape parameter
\text{scale}: Scale parameter
\text{PDF}(x) = \frac{x^{a-1} e^{-x / \text{scale}}}{\text{scale}^a \Gamma(a)}
Chi Square
A chi-squared continuous random variable: the sum of the squares of \nu independent standard normal values. The mean is \nu.
\chi^2(\nu)
\nu: Degrees of freedom
\text{PDF}(x) = \frac{1}{2^{\nu/2} \Gamma(\nu/2)} x^{\nu/2 - 1} e^{-x/2}
Pareto
A Pareto (Type I) continuous random variable, in the form that both AddParetoRandomVariable and SetSampleRDSPareto use. Its values have a long upper tail: most values are near the smallest value, and a few are much larger. A smaller \gamma gives a longer tail.
\text{pareto}(\gamma, \text{loc}, \text{scale})
\gamma: Shape parameter (tail index)
\text{loc}: Location parameter (shift)
\text{scale}: Scale parameter; the minimum possible value is \text{loc} + \text{scale}
\text{PDF}(x) = \frac{\gamma}{\text{scale}} \left( \frac{x - \text{loc}}{\text{scale}} \right)^{-\gamma - 1} for x \geq \text{loc} + \text{scale}
Student’s t
A Student’s t continuous random variable. The values spread symmetrically around 0, and values far from 0 are more likely than with a standard normal distribution. With more degrees of freedom, the distribution is closer to the standard normal distribution.
\text{T}(\nu)
\nu: Degrees of freedom
\text{PDF}(x) = \frac{\Gamma((\nu+1)/2)}{\sqrt{\nu \pi} \Gamma(\nu/2)} \left(1 + \frac{x^2}{\nu}\right)^{-(\nu+1)/2}
Weibull
A Weibull minimum extreme value continuous random variable: a positive value, often used for a time to failure. With c = 1, it is the exponential distribution with the mean \text{scale}.
\text{weibull}_\text{min}(c, \text{scale})
c: Shape parameter
\text{scale}: Scale parameter
\text{PDF}(x) = \frac{c}{\text{scale}} \left( \frac{x}{\text{scale}} \right)^{c-1} \exp\left( -\left( \frac{x}{\text{scale}} \right)^c \right)
Linking OptQuest To Your Project
OptTek ships the OptQuest Engine with bindings for Java, C#, C++, C and Python. This section describes how to add OptQuest to a project in each language.
Java
OptQuest for Java is one file, OptQuest.jar. Add it to your project as a library. It contains both the OptQuest 9 API and the OptQuest 10 API.
C#
OptQuest for C# is two files: OptQuestEngine.dll, the engine, and OptQuestNet.dll, the C# binding. Add a reference to OptQuestNet.dll to your project. At run time both DLLs must be in the same directory. The distribution includes a Visual Studio solution with working examples.
C++
OptQuest for C++ is OptQuestEngine.dll and OptQuestLib.dll, which together hold the engine, plus the header optquest.h and the import library OptQuestLib.lib, which hold the C++ binding. Include the header, link OptQuestLib.lib, and put OptQuestLib.dll and OptQuestEngine.dll in the same directory as your application at run time. The distribution includes a Visual Studio solution with working examples.
C
OptQuest for C uses the same files as C++: OptQuestEngine.dll and OptQuestLib.dll hold the engine, and optquest.h and OptQuestLib.lib hold the C binding. Include the header, link OptQuestLib.lib, and put OptQuestLib.dll and OptQuestEngine.dll in the same directory as your application at run time. The distribution includes a Visual Studio solution with working examples.
Array Arguments From a Host That Cannot Build a Pointer Array
Twelve C entry points take an array of pointers to rows: ten take rows of numbers (const double**) and two take rows of strings (const char***). Seventeen take an array of strings (const char** or const char***). A host such as MATLAB or IDL can pass a contiguous buffer but not an array of pointers, so each of those functions has a second form that takes the data in one piece:
...Flattakes one contiguous row-major buffer instead of the row pointers. Element(i, j)isflat[i * ncols + j], so a column-major caller passes the transpose.OQAddTupleVariableFlat,OQAddGeolocationVariableFlat,OQAddPolicySequenceVariableFlat,OQAddRegionVariableFlat,OQAddSphericalRegionVariableFlat,OQAddLowRankCorrectionMatrixVariableFlat,OQAddIncrementalLowRankCorrectionMatrixVariableFlat,OQAddBSplineCorrectionMatrixVariableFlat,OQAddSplineCorrectionMatrixVariableFlat,OQAddFourierCorrectionMatrixVariableFlat,OQAddExchangeableGroupFlat2DandOQAddMultiStageSequenceVariableFlat....Blobtakes the string array as one string whose elements are joined by ASCII0x01, plus the element count.OQAddPermutationVariableBlob,OQAddSelectionVariableBlob,OQAddFixGroupBlob,OQAddFloatGroupBlob,OQAddExchangeableGroupFlatBlob,OQAddExchangeableGroupBlob,OQAddMixtureVariableBlob,OQAddSequenceVariableBlob,OQAddMultiStageSequenceVariableBlob,OQAddPolicySequenceVariableBlob,OQAddMultiChoiceVariableBlob,OQAddDAGVariableBlob,OQAddDAGVariableFullBlob,OQAddTreeVariableBlob,OQAddTreeVariableFullBlob,OQAddTopologicalSequenceVariableBlobandOQAddPathVariableBlob.
Each variant calls the same implementation as the pointer-array form, so the two validate the same way, fail the same way and produce identical Describe() text. OQAddExchangeableGroupFlat2D is the two-dimensional group. OQAddExchangeableGroupFlat is the one-dimensional form, with one variable for each item.
Python
OptQuest for Python is optquest.py, the binding, plus the engine library for the platform:
- Windows:
OptQuestLib.dllplusOptQuestEngine.dll. Windows finds the engine on its own when the two DLLs are in the same directory. - Linux:
libOptQuestLib.soplus the matching engine shared library.
By default optquest.py loads the library from its own directory. To load it from elsewhere, set the module-level dll_path before you create the first OptQuestModel:
import optquest
optquest.dll_path = "/path/to/library/directory"
model = optquest.OptQuestModel()COM (VBA, VBScript, VB6, Excel)
OptQuest also has a COM interface for Automation clients that cannot link the .NET, C++ or C libraries. OptQuestCOM.dll registers it. It has three creatable objects:
| ProgID | Purpose |
|---|---|
OptQuestNet.OptQuestModelCOM |
The model, the COM form of OptQuestModel |
OptQuestNet.OptQuestSolutionCOM |
A solution, the COM form of OptQuestSolution |
OptQuestNet.OptQuestConstantsCOM |
The constants, as read-only properties (see below) |
Dim model As Object
Set model = CreateObject("OptQuestNet.OptQuestModelCOM")
model.AddContinuousVariable "x", 0, 10
model.AddMaximizeObjective "profit", "3*x"The COM surface is the C# surface with the adjustments that Automation requires:
- Arrays are VARIANT arrays. Every list parameter is declared as
object[], and every 2-D parameter as a singleobjectthat the wrapper casts toobject[,]. The wrapper reads an array from its own lower bound, so VBA’s 1-based arrays andRange.Valuefrom Excel both work without reindexing. - No overloads. Where the other languages overload a name, COM uses distinct names:
AddAssignmentVariableHom/AddAssignmentVariableHet,AddItemSelectionVariableRange,AddBudgetedSelectionVariableFull,AddDAGVariableFull,AddTreeVariableFull,AddExchangeableGroupFlat,SetReplicationsFixed. - Concurrency uses explicit names.
ParallelOptimize(npar, nsol, evaluator, monitor)andParallelSample(...)correspond to the(npar, nsol, ...)overloads.CreateAsyncChannel(npar)returns anIOptQuestModelChannelCOM, which you pass toAsyncOptimize(...)orAsyncSample(...). - Callbacks are interfaces. Implement
IOptQuestEvaluatorCOM(Evaluate(sol)) andIOptQuestMonitorCOM(Monitor(sol)), or passNothingfor either. - Errors follow the C# convention. A failing call returns
False. CallGetLastError()on the model or the solution for the description. - Constants are properties of one object. Create the object with the ProgID
OptQuestNet.OptQuestConstantsCOMand read each constant from it as a read-only property. The name of a property is the prefix of its constant class followed by the C# name of the constant in capital letters. The prefixes areSTATISTIC_forStatistic,CONFIDENCE_forConfidence,SAMPLEMETHOD_forSampleMethod,SAMPLEVARIOGRAM_forSampleVariogramandTERMINATION_forTerminationReason. For example,OptQuestModel.Confidence.Level95in C# isCONFIDENCE_LEVEL95in COM, andOptQuestModel.TerminationReason.OptimalFoundisTERMINATION_OPTIMALFOUND. TheSAMPLEVARIOGRAM_properties are strings, and all the other properties are integers. In the type library, the properties are members of the interfaceIOptQuestConstantsCOM. VBScript cannot declare aConstfrom a property, so keep the object in a variable:
Dim consts
Set consts = CreateObject("OptQuestNet.OptQuestConstantsCOM")
model.SetObjectiveConfidence "obj", consts.CONFIDENCE_TYPE2, consts.CONFIDENCE_LEVEL95, 0.05The IID of IOptQuestModelCOM changed in OptQuest 10.1, and the IID of IOptQuestSolutionCOM changed in OptQuest 10.2. A client that binds late (CreateObject and Object variables), as in the example above, needs no change. A client with an early-bound reference to an earlier type library must refresh it.
The distribution includes 90 example programs in the directory examples. OptQuest 10.2 Examples for COM (VBScript) explains each one.
Standard I/O Interface
For expert use only. The engine can also run as a standalone process that reads commands from standard input and writes replies to standard output. Use this interface only when your application cannot link one of the OptQuest libraries (Java, C#, C++, C or Python). It supports the manual optimization loop: the client requests each solution, evaluates it, and submits or rejects it.
Setup
OptQuest.jarcontains the server as itsmain()function. Runjava -jar OptQuest.jarto start it. The server reads commands from STDIN and writes replies to STDOUT.- Any host that can start a process and read and write its pipes can use the server. The wire format below is the whole interface.
Interface Characteristics
- Command format:
- Most commands are one line, terminated by an end-of-line character (
\n), with the parameters separated by spaces. - Some commands span several lines, one option per line, and end with a line that contains only
END.
- Most commands are one line, terminated by an end-of-line character (
- Reply format:
- Most replies are one line, terminated by an end-of-line character.
- An error reply begins with
ERRORand can span several lines. Read until the input buffer is empty.
- Errors:
- A command the server cannot carry out gets a reply that begins with
ERROR. The session stays usable. - The server reports an error for an unrecognized model-definition statement, for a value line with a name that the model does not declare, and for a malformed identifier.
- An error during parsing, including stack exhaustion on a pathological expression, comes back as an
ERRORreply and does not stop the server.
- A command the server cannot carry out gets a reply that begins with
- Scope:
- The interface supports the manual optimization loop in which the client requests each solution creation, then manages evaluation and submission.
- A library integration is easier to debug, because a failure is a return code at the call site rather than a reply to parse.
In-Process Variant (OQCore*)
The same commands are also available in-process, with no subprocess and no pipe. OptQuestLib exports one C function per command. Each takes the command’s argument string and returns the reply:
char* OQCoreCreateModel(const char* block);
char* OQCoreCreateSolution(const char* optid);
char* OQCoreSubmitSolution(const char* solution);
char* OQCoreRejectSolution(const char* solution);
char* OQCorePredictSolution(const char* solution);
char* OQCoreEvaluateSolution(const char* solution);
char* OQCoreAddSolution(const char* solution);
char* OQCoreGetSolution(const char* args);
char* OQCoreGetBestSolutions(const char* args);
char* OQCoreGetAllSolutions(const char* optid);
char* OQCoreAddAllSolutions(const char* args);
char* OQCoreCopySolution(const char* args);
char* OQCoreGetTerminationReason(const char* optid);
char* OQCoreSetTerminationReason(const char* args);
char* OQCoreGetNames(const char* optid);
char* OQCoreDeleteModel(const char* optid);
char* OQCoreGetVersionInfo(void);
void OQCoreFree(char* s);There are three differences from the subprocess interface:
- No envelope. The function name is the verb, so there is no
CREATEMODELline and no terminatingEND.OQCoreCreateModeltakes the bare block of model-definition commands. - The caller owns the reply. Every
OQCore*function that returnschar*returns a heap string that the engine isolate allocated. Release it withOQCoreFree, notfree(). - Calls are serialized on the engine isolate mutex, so the interface is safe to call from several threads, one command at a time.
The command syntax, the model-definition commands and the reply formats are the same as in the STDIO reference below. OQCore<Command> is the in-process spelling of <COMMAND>.
This surface exists for tooling that already builds command strings (YAML or DSL front ends, agent integrations, code generators) and can hand them to the engine directly. For ordinary integration work, use the typed API. The Python binding wraps this layer as its OptQuestCore class.
Command List
The STDIO interface covers the manual optimization loop: model creation, solution request, evaluation and result retrieval. The table lists each command and its equivalent in the typed API.
| Command | Description | API Equivalent |
|---|---|---|
CREATEMODEL |
Creates a new model object. | new OptQuestModel() |
CREATESOLUTION |
Generates a new solution for evaluation, populated with input variable values. | model.CreateSolution() |
SUBMITSOLUTION |
Submits an evaluated solution to the optimization engine for processing. | solution.Submit() |
REJECTSOLUTION |
Rejects a solution that could not be evaluated. | solution.Reject() |
PREDICTSOLUTION |
Uses the internal metamodel to predict the response of a solution. | solution.Predict() |
EVALUATESOLUTION |
Computes a solution’s expressions, constraints, and objectives without submitting it. | solution.Evaluate() |
ADDSOLUTION |
Adds a suggested (input-only), required (input-only, used as given), or evaluated (input and output) solution to the model. | solution.AddSuggested() solution.AddEvaluated() solution.AddRequired() |
GETSOLUTION |
Retrieves the values of an evaluated solution after the engine has processed it. | solution.Update() |
GETBESTSOLUTIONS |
Retrieves the best solutions, either the n-best or the Pareto frontier. | model.GetBestSolutions(limit) |
GETALLSOLUTIONS |
Retrieves all evaluated solutions from the model. | model.GetAllSolutions() |
ADDALLSOLUTIONS |
Copies all solutions from a source model to a destination model. | model.AddAllSolutions(srcModel) |
COPYSOLUTION |
Copies one solution into a model, with the same values for every variable. | model.CopySolution(src) |
GETNAMES |
Retrieves the model’s input and output variable names, in declaration order. | solution.GetInputNames() solution.GetOutputNames() |
DELETEMODEL |
Deletes a model, freeing associated resources. | OptQuestModel destructor |
VERSIONINFO |
Returns the version info about the engine. | OptQuest.GetVersionInfo() |
QUIT |
Terminates the OptQuest STDIO server, closing the session. |
Command Reference
Each command below is documented with its wire format and the format of its reply. The commands are listed in the order of a typical session: model definition, solution generation, evaluation and result retrieval, then model deletion and session end.
Solution Replies
Several commands reply with a solution. There are two shapes.
The short form (CREATESOLUTION, COPYSOLUTION) is:
- First line: two integers,
<modelIdentifier>and<solutionIdentifier>. - Second line: seven integers:
<iteration>: the iteration number of the solution.<replication>: the replication number of this instance.<numberOfReplications>: the number of replications of the iteration that are complete. For a solution fromCREATESOLUTIONthat is not yet submitted or rejected, it is<replication>minus 1.<isComplete>:1if all replications are complete,0otherwise. It is0for a solution fromCREATESOLUTIONthat is not yet submitted or rejected.<isFeasible>:1if the solution satisfies every constraint,0otherwise.<hasMetConfidence>:1if the confidence requirements are met (variable-replication mode),0otherwise.<isEvaluated>:1if the solution was added withAddEvaluatedand already has its output values,0otherwise (0for a solution the engine generated).
- Following lines: one
<name> <value>pair per line for each input variable, then for each output variable. An entry whose value is NaN is omitted. The outputs that your evaluator writes are NaN in a solution fromCREATESOLUTION, so output lines appear only for a solution that was added with its output values (AddEvaluated) and for the values that the engine computes, such as expression variables.
<modelIdentifier> <solutionIdentifier>
<iteration> <replication> <numberOfReplications> <isComplete> <isFeasible> <hasMetConfidence> <isEvaluated>
<inputName1> <inputValue1>
...
<inputNameN> <inputValueN>
The full form (GETSOLUTION, PREDICTSOLUTION, EVALUATESOLUTION, and each solution in a GETBESTSOLUTIONS or GETALLSOLUTIONS reply) has the same first two lines, followed by one <name> <value> pair per line for:
- Input variables:
<inputName>and its value. - Output variables: the aggregated
<outputName>and its value, then one line per replication as<outputName;R>for replicationR. - Objectives: the aggregated
<objectiveName>and its value, the confidence width as<objectiveName;cw>, then one line per replication as<objectiveName;R>. - Constraints: the feasibility as
<constraintName>(1.0feasible,0.0infeasible), then the left-hand and right-hand side of each clauseCas<constraintName;LHS;C>and<constraintName;RHS;C>.
<modelIdentifier> <solutionIdentifier>
<iteration> <replication> <numberOfReplications> <isComplete> <isFeasible> <hasMetConfidence> <isEvaluated>
<inputName1> <inputValue1>
...
<inputNameN> <inputValueN>
<outputName1> <outputValue1>
<outputName1;1> <outputValue1Replication1>
...
<outputName1;R> <outputValue1ReplicationR>
...
<objectiveName1> <objectiveValue1>
<objectiveName1;cw> <objectiveConfidenceWidth1>
<objectiveName1;1> <objectiveValue1Replication1>
...
<objectiveName1;R> <objectiveValue1ReplicationR>
...
<constraintName1> <constraintFeasibility1>
<constraintName1;LHS;1> <constraintLeftHandSideValue1Clause1>
<constraintName1;RHS;1> <constraintRightHandSideValue1Clause1>
...
<constraintName1;LHS;C> <constraintLeftHandSideValue1ClauseC>
<constraintName1;RHS;C> <constraintRightHandSideValue1ClauseC>
...
Create Model
Command Format
CREATEMODEL spans several lines. It begins with the line CREATEMODEL, continues with one model-definition command per line, and ends with a line that contains only END. Each model-definition command is one line with space-separated parameters.
CREATEMODEL
...model definition commands...
END
Model Definition Commands
Each model-definition command starts with an identifier followed by one or more parameters, separated by spaces unless the table says otherwise. The table lists the commands and their equivalents in the typed API. Identifiers are case-insensitive, so continuous, CONTINUOUS and Continuous are all accepted.
The server skips blank and whitespace-only lines and ignores leading whitespace, so a block can be indented. An identifier that is not in the table is an error: the server does not create the model, so you cannot get a model that silently lacks a variable or a setting because of a misspelling.
| Command | Parameters | Equivalent API Function |
|---|---|---|
LICENSE |
<license> |
model.SetLicense(license) |
LOGSETUP |
<filespec> (the rest of the line; may contain spaces) |
model.LogSetup(filespec) |
LOGSOLUTIONS |
<filespec> (the rest of the line; may contain spaces) |
model.LogSolutions(filespec) |
CONTINUOUS |
<name> <min> <max> |
model.AddContinuousVariable(name, min, max) |
INTEGER |
<name> <min> <max> |
model.AddIntegerVariable(name, min, max) |
DISCRETE |
<name> <min> <max> <step> |
model.AddDiscreteVariable(name, min, max, step) |
BINARY |
<name> |
model.AddBinaryVariable(name) |
DESIGN |
<name> <num> |
model.AddDesignVariable(name, num) |
ENUMERATION |
<name> <items> <items>: Space-delimited list of doubles |
model.AddEnumerationVariable(name, items) |
PERMUTATION |
<group> <names> <names>: Space-delimited list of strings |
model.AddPermutationVariable(group, names) |
TUPLE |
<name> <tuples> <tuples>: Comma-separated values, semicolon-separated tuples (for example a,b,c;d,e,f)1 |
model.AddTupleVariable(name, tuples) |
GEOLOCATION |
<name> <locations> <locations>: Comma-separated lat/lon pairs, semicolon-separated (for example lat1,lon1;lat2,lon2)1 |
model.AddGeolocationVariable(name, locations) |
SELECTION |
<name> <selVars> <selVars>: Space-delimited list of strings |
model.AddSelectionVariable(name, selVars) |
EXCHANGE |
<name> <group> <group>: Comma-separated values, semicolon-separated groups (for example x1,y1,z1;x2,y2,z2)1 4 |
model.AddExchangeableGroup(name, group) |
FIXGROUP |
<name> <variables> <variables>: Space-delimited list of strings |
model.AddFixGroup(name, variables) |
FLOATGROUP |
<name> <variables> <variables>: Space-delimited list of strings |
model.AddFloatGroup(name, variables) |
EXCLUSIVE |
<name> <min> <max> |
model.AddVariableExclusiveRange(name, min, max) |
VECTOR |
<name> <n> <min> <max> |
model.AddVectorVariable(name, n, min, max) |
MATRIX |
<name> <m> <n> <min> <max> |
model.AddMatrixVariable(name, m, n, min, max) |
ANGLE |
<name> <minDeg> <maxDeg> |
model.AddAngleVariable(name, minDeg, maxDeg) |
SPHERICALANGLE |
<name> <minThetaDeg> <maxThetaDeg> <minPhiDeg> <maxPhiDeg> |
model.AddSphericalAngleVariable(name, minThetaDeg, maxThetaDeg, minPhiDeg, maxPhiDeg) |
MIXTURE |
<name> <k\|c1,c2,...> [<lowerBounds> <upperBounds>] [<sumTo>] |
model.AddMixtureVariable(name, components, lowerBounds, upperBounds, sumTo)(components = a component count or comma-separated names; bounds are optional but must appear as a matched pair, each either a comma-separated list of k values or a single value broadcast to every component; sumTo is optional and defaults to 1.0) |
SEQUENCE |
<name> <c1,c2,...> [<topK>] |
model.AddSequenceVariable(name, components, topK)(components = comma-separated names; topK is optional) |
MULTISTAGESEQUENCE |
<name> <stage1c1,stage1c2,...;stage2c1,stage2c2,...;...> |
model.AddMultiStageSequenceVariable(name, stageGroups)(semicolon between stages, comma within each stage) |
POLICYSEQUENCE |
<name> <item1,item2,...> <feat1,feat2,...> <r1c1,r1c2,...;r2c1,r2c2,...;...> |
model.AddPolicySequenceVariable(name, featureMatrix, itemNames, featureNames)(item names, then feature names, then the feature matrix; semicolon between matrix rows, comma within names and within each row) |
CHOICE |
<name> <k> |
model.AddChoiceVariable(name, k) |
MULTICHOICE |
<name> <choice1,choice2,...> <minSelect> <maxSelect> |
model.AddMultiChoiceVariable(name, choices, minSelect, maxSelect) |
ASSIGNMENT |
Simple: <name> <m> <n> Homogeneous: <name> <m> <n> <mustAssign> <binCapMin> <binCapMax> Heterogeneous: <name> <m> <n> <b1,...,bm> <min1,...,minn> <max1,...,maxn>; mustAssign values are true/false; comma-separated arrays distinguish heterogeneous from homogeneous |
model.AddAssignmentVariable(name, m, n) model.AddAssignmentVariable(name, m, n, mustAssign, binCapMin, binCapMax) model.AddAssignmentVariable(name, m, n, mustAssign[], binCapMins[], binCapMaxs[]) |
ITEMSELECTION |
Exact: <name> <n> <k> Range: <name> <n> <kMin> <kMax>; four tokens = range form, three = exact form |
model.AddItemSelectionVariable(name, n, k) model.AddItemSelectionVariable(name, n, kMin, kMax) |
BUDGETEDSELECTION |
Simple: <name> <n> <budgetMax> <c1,...,cn> Full: <name> <n> <budgetMin> <budgetMax> <kMin> <kMax> <c1,...,cn>; six tokens before the cost array = full form, three = simple form |
model.AddBudgetedSelectionVariable(name, n, costs, budgetMax) model.AddBudgetedSelectionVariable(name, n, costs, budgetMin, budgetMax, kMin, kMax) |
PARTITION |
<name> <m> <k> |
model.AddPartitionVariable(name, m, k) |
LOWRANK |
<name> <rows> <cols> <rank> <min> <max> |
model.AddLowRankMatrixVariable(name, rows, cols, rank, min, max) |
LOWRANKCORRECTION |
<name> <initial_matrix> <rank> <min> <max> |
model.AddLowRankCorrectionMatrixVariable(name, initial, rank, min, max)(initial_matrix = semicolon between rows, comma within rows) |
LOWRANKINCREMENTAL |
<name> <initial_matrix> <rank> <min> <max> |
model.AddIncrementalLowRankCorrectionMatrixVariable(name, initial, rank, min, max)(initial_matrix = semicolon between rows, comma within rows) |
TIMESERIESVECTOR |
<name> <longScale> <shortScale> <rank> <min> <max> |
model.AddTimeSeriesVectorVariable(name, longScale, shortScale, rank, min, max) |
TIMESERIESCORRECTIONVECTOR |
<name> <initial> <longScale> <shortScale> <rank> <min> <max> |
model.AddTimeSeriesCorrectionVectorVariable(name, initial, longScale, shortScale, rank, min, max)(initial = comma-separated doubles) |
TIMESERIESINCREMENTALVECTOR |
<name> <initial> <longScale> <shortScale> <rank> <min> <max> |
model.AddIncrementalTimeSeriesCorrectionVectorVariable(name, initial, longScale, shortScale, rank, min, max)(initial = comma-separated doubles) |
BSPLINEVECTOR |
<name> <length> <numKnots> <min> <max> |
model.AddBSplineVectorVariable(name, length, numKnots, min, max) |
SPLINEVECTOR |
<name> <length> <numKnots> <min> <max> |
model.AddSplineVectorVariable(name, length, numKnots, min, max) |
BSPLINECORRECTIONVECTOR |
<name> <initial> <numKnots> <min> <max> |
model.AddBSplineCorrectionVectorVariable(name, initial, numKnots, min, max)(initial = comma-separated doubles) |
SPLINECORRECTIONVECTOR |
<name> <initial> <numKnots> <min> <max> |
model.AddSplineCorrectionVectorVariable(name, initial, numKnots, min, max)(initial = comma-separated doubles) |
BSPLINEMATRIX |
<name> <rows> <cols> <knotRows> <knotCols> <min> <max> |
model.AddBSplineMatrixVariable(name, rows, cols, knotRows, knotCols, min, max) |
SPLINEMATRIX |
<name> <rows> <cols> <knotRows> <knotCols> <min> <max> |
model.AddSplineMatrixVariable(name, rows, cols, knotRows, knotCols, min, max) |
BSPLINECORRECTIONMATRIX |
<name> <initial_matrix> <knotRows> <knotCols> <min> <max> |
model.AddBSplineCorrectionMatrixVariable(name, initial_matrix, knotRows, knotCols, min, max)(initial_matrix = semicolon between rows, comma within rows) |
SPLINECORRECTIONMATRIX |
<name> <initial_matrix> <knotRows> <knotCols> <min> <max> |
model.AddSplineCorrectionMatrixVariable(name, initial_matrix, knotRows, knotCols, min, max)(initial_matrix = semicolon between rows, comma within rows) |
FOURIERVECTOR |
<name> <length> <numFreq> <min> <max> |
model.AddFourierVectorVariable(name, length, numFreq, min, max) |
FOURIERMATRIX |
<name> <rows> <cols> <freqRows> <freqCols> <min> <max> |
model.AddFourierMatrixVariable(name, rows, cols, freqRows, freqCols, min, max) |
FOURIERCORRECTIONVECTOR |
<name> <initial> <numFreq> <min> <max> |
model.AddFourierCorrectionVectorVariable(name, initial, numFreq, min, max)(initial = comma-separated doubles) |
FOURIERCORRECTIONMATRIX |
<name> <initial_matrix> <freqRows> <freqCols> <min> <max> |
model.AddFourierCorrectionMatrixVariable(name, initial_matrix, freqRows, freqCols, min, max)(initial_matrix = semicolon between rows, comma within rows) |
REGION |
<name> <vertices> |
model.AddRegionVariable(name, polygon)(vertices formatted as x1,y1;x2,y2;...) |
SPHERICALREGION |
<name> <vertices> |
model.AddSphericalRegionVariable(name, polygon)(vertices formatted as theta1,phi1;theta2,phi2;...) |
DAG |
<name> node1,...,nodeN [<start>;<end>;<connected>;<dependent1,pred1,pred2;dependent2,pred3,...>] |
model.AddDAGVariable(name, nodeNames, startNode, endNode, connected, predecessors)(the options token is optional; an empty field leaves that option unset, and connected is 0 or 1. Example: DAG g S,A,B,T S;T;1;B,A has start S, end T, connected, and B after A.) |
TREE |
<name> node1,...,nodeN [<root>;<dependent1,pred1,pred2;dependent2,pred3,...>] |
model.AddTreeVariable(name, nodeNames, rootNode, predecessors)(the options token is optional; an empty root leaves the root free. Example: TREE t hq,east,west,north hq has the root hq.) |
PATH |
<name> <node1,node2,...> <startNode>;<endNode>;<required1,required2,...> |
model.AddPathVariable(name, nodeNames, startNode, endNode, requiredNodes) |
TOPOLOGICALSEQUENCE |
<name> <task1,task2,...> <dependent1,pred1,pred2;dependent2,pred3,...> |
model.AddTopologicalSequenceVariable(name, tasks, predecessors)(predecessor rows separated by ;; within each row, the first name is the dependent task and the rest are its predecessors. Example: tasks A,B,C,D with predecessor list B,A;C,A;D,B,C means B requires A; C requires A; D requires B and C.) |
BETARANDOM |
<name> <alpha> <beta> |
model.AddBetaRandomVariable(name, alpha, beta) |
CAUCHYRANDOM |
<name> <location> <scale> |
model.AddCauchyRandomVariable(name, location, scale) |
CHISQRANDOM |
<name> <df> |
model.AddChiSquareRandomVariable(name, df) |
EXPONENTIALRANDOM |
<name> <scale> |
model.AddExponentialRandomVariable(name, scale) |
GAMMARANDOM |
<name> <shape> <scale> |
model.AddGammaRandomVariable(name, shape, scale) |
LOGNORMALRANDOM |
<name> <shape> <scale> |
model.AddLogNormalRandomVariable(name, shape, scale) |
NORMALRANDOM |
<name> <mean> <sigma> |
model.AddNormalRandomVariable(name, mean, sigma) |
PARETORANDOM |
<name> <gamma> <loc> <scale> |
model.AddParetoRandomVariable(name, gamma, loc, scale) |
POISSONRANDOM |
<name> <lambda> |
model.AddPoissonRandomVariable(name, lambda) |
POWERRANDOM |
<name> <rmin> <rmax> <power> |
model.AddPowerRandomVariable(name, rmin, rmax, power) |
SPHERICALRANDOM |
<name> <min> <max> |
model.AddSphericalElevationRandomVariable(name, min, max) |
STUDENTTRANDOM |
<name> <df> |
model.AddStudentTRandomVariable(name, df) |
UNIFORMRANDOM |
<name> <min> <max> |
model.AddUniformRandomVariable(name, min, max) |
WEIBULLRANDOM |
<name> <shape> <scale> |
model.AddWeibullRandomVariable(name, shape, scale) |
OUTPUT |
<name> |
model.AddOutputVariable(name) |
OUTPUTSTATISTIC |
<name> <statistic> <statisticValue> |
model.SetOutputStatistic(name, statistic, statisticValue) |
OUTPUTVECTOR |
<name> <n> |
model.AddOutputVectorVariable(name, n) |
OUTPUTMATRIX |
<name> <rows> <cols> |
model.AddOutputMatrixVariable(name, rows, cols) |
BINARYVECTOR |
<name> <n> |
model.AddBinaryVectorVariable(name, n) |
BINARYMATRIX |
<name> <m> <n> |
model.AddBinaryMatrixVariable(name, m, n) |
INTEGERVECTOR |
<name> <n> <min> <max> |
model.AddIntegerVectorVariable(name, n, min, max) |
INTEGERMATRIX |
<name> <m> <n> <min> <max> |
model.AddIntegerMatrixVariable(name, m, n, min, max) |
DISCRETEVECTOR |
<name> <n> <min> <max> <step> |
model.AddDiscreteVectorVariable(name, n, min, max, step) |
DISCRETEMATRIX |
<name> <m> <n> <min> <max> <step> |
model.AddDiscreteMatrixVariable(name, m, n, min, max, step) |
NDVARIABLE |
<name> <d1,d2,...> <min> <max> |
model.AddNDVariable(name, dims, min, max)(dims = comma-separated integers, for example 3,4,2) |
INTEGERNVARIABLE |
<name> <d1,d2,...> <min> <max> |
model.AddIntegerNDVariable(name, dims, min, max)(dims = comma-separated integers) |
DISCRETENDVARIABLE |
<name> <d1,d2,...> <min> <max> <step> |
model.AddDiscreteNDVariable(name, dims, min, max, step)(dims = comma-separated integers) |
BINARYNDVARIABLE |
<name> <d1,d2,...> |
model.AddBinaryNDVariable(name, dims)(dims = comma-separated integers) |
OUTPUTNDVARIABLE |
<name> <d1,d2,...> |
model.AddOutputNDVariable(name, dims)(dims = comma-separated integers) |
OBJECTIVE |
<name> <direction> <expression> <direction>: MIN or MAX |
model.AddMinimizeObjective(name, expression) (if MIN) model.AddMaximizeObjective(name, expression) (if MAX) |
OBJECTIVEGOAL |
<name> <min> <max> |
model.SetObjectiveGoal(name, min, max) |
OBJECTIVECONFIDENCE |
<name> <ctype> <clevel> <epct> (epct is a fraction greater than 0 and less than 1, such as 0.05) |
model.SetObjectiveConfidence(name, ctype, clevel, epct) |
OBJECTIVESTATISTIC |
<name> <statistic> <statisticValue> |
model.SetObjectiveStatistic(name, statistic, statisticValue) |
CONSTRAINT |
<name> <expression> |
model.AddConstraint(name, expression) |
EXPRESSION |
<name> <expression> |
model.AddExpressionVariable(name, expression) |
REPLICATIONS |
<min> <max> (min ≥ 1, max ≥ min; max of 1 runs without replications) |
model.SetReplications(min, max) |
SERIALREPLICATIONS |
None | model.SetSerialReplications() |
PARALLELHINT |
<npar> |
model.SetParallelHint(npar) |
RANDOMSEED |
<seed> |
model.SetRandomSeed(seed) |
STOPMILP |
None | model.StopOnSuccessfulMILP() |
NOGENERATE |
None | model.SuggestedSolutionsOnly() |
STOPCYCLES |
<cycles> |
model.SetStopCycles(cycles) |
STOPIMPROVEMENT |
<improvement> <iterations> |
model.SetStopImprovement(improvement, iterations) |
STOPTIME |
<seconds> |
model.SetStopTime(seconds) |
METRIC |
<name> <response>;<error>2 |
model.AddSampleMetric(name, response, error) |
SAMPLE |
<method> |
model.SetSampleMethod(method) |
VARIOGRAM |
<variogram> |
model.SetSampleVariogram(variogram) |
RDSBINS |
<name> <distribution> <params>3 |
model.SetSampleRDSUniform(...)model.SetSampleRDSNormal(...)model.SetSampleRDSLogNormal(...)model.SetSampleRDSBeta(...)model.SetSampleRDSPoisson(...)model.SetSampleRDSExponential(...)model.SetSampleRDSCauchy(...)model.SetSampleRDSGamma(...)model.SetSampleRDSChiSquare(...)model.SetSampleRDSPareto(...)model.SetSampleRDST(...)model.SetSampleRDSWeibull(...)model.SetSampleRDSDiscrete(...) |
1 Tuple and geolocation format: tuples and geolocations are one string, with commas between the values of a tuple or coordinate pair and semicolons between tuples or pairs. For example, the four tuples (a,b,c), (d,e,f), (g,h,i) and (j,k,l) are written a,b,c;d,e,f;g,h,i;j,k,l, and geolocations are written lat1,lon1;lat2,lon2.
2 Metric expressions: a semicolon (;) separates responseExpression and errorExpression in the METRIC command, so that the expressions can contain spaces. The semicolon is a separator inside the METRIC command only. Variable, constraint and objective names still must not contain semicolons.
3 Response distribution parameters: distribution is the name of the distribution, and params is a space-separated list of values. For a continuous distribution (UNIFORM, NORMAL, BETA and so on), params begins with nBins, the number of histogram bins, followed by the parameters of the distribution, for example nBins mu sigma for NORMAL. For DISCRETE, params has no nBins; it is the list of bin edges, for example 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 for ten equal bins on [0,1]. The number of bins is one more than the number of edges.
4 Exchangeable group members: a member can be a generated element name with commas, such as m@1,2. The engine splits each group on the commas and then joins a part that starts with a digit to the member before it, because a variable name cannot start with a digit. Thus m@1,1,m@1,2;m@2,1,m@2,2 holds the two groups (m@1,1, m@1,2) and (m@2,1, m@2,2). A comma in a member name must be followed by a digit.
Return
A single integer, the identifier of the new model.
On error, the reply begins with ERROR followed by a description. A statement the parser does not recognize, or one the model rejects, gets ERROR CREATING OPTIMIZATION: type=<identifier> name=<name>.
<modelIdentifier>
Create Solution
Command Format
One line with one parameter, the integer identifier of the model.
CREATESOLUTION <modelIdentifier>
Return
The short form of the solution reply (see § Solution Replies).
When the engine has no solution to offer (the search space is exhausted, a stop criterion was met, or the run was interrupted), the reply is ERROR CANNOT CREATE; REASON = <n>, where <n> is the termination reason code. This is the normal end of a manual loop, not a fault. Any other reply that begins with ERROR is a failure, followed by a description.
Submit Solution
Command Format
Several lines, to submit an evaluated solution:
- First line: the bare verb
SUBMITSOLUTION, alone on its line. The engine dispatches on it and reads the arguments from the next line. - Second line: two integers,
<modelIdentifier>and<solutionIdentifier>. - Following lines: one
<variableName> <variableValue>pair per line for each output variable, and for each input variable that was changed during evaluation. An output that the lines leave out stays NaN, so each objective and constraint that uses it is NaN and the solution is infeasible. Blank lines are ignored. Objective and constraint names are accepted and ignored, so a solution read back withGETSOLUTION,GETBESTSOLUTIONSorGETALLSOLUTIONScan be sent back unchanged; the engine computes their values and does not accept them from the client. - Last line:
END.
SUBMITSOLUTION
<modelIdentifier> <solutionIdentifier>
<variableName1> <variableValue1>
...
<variableNameN> <variableValueN>
END
Return
A single integer: the number of iterations the model has completed, including this one. 0 is a valid reply while no iteration is complete.
On error (for example, an invalid solution ID), the reply begins with ERROR followed by a description. Two errors concern the value lines:
ERROR BAD VALUE NAME: <name>: the model declares no input or output with that name.ERROR BAD VALUE LINE: <line>: the line has a name with no value.
<numberCompleted>
Reject Solution
Command Format
One line with two integer parameters, <modelIdentifier> and <solutionIdentifier>, to reject a solution that could not be evaluated.
REJECTSOLUTION <modelIdentifier> <solutionIdentifier>
Return
A single integer: the number of iterations the model has completed, including this one. 0 is a valid reply while no iteration is complete.
On error (for example, an invalid solution ID), the reply begins with ERROR followed by a description.
<numberCompleted>
Predict Solution
Command Format
Several lines, to predict the response of a candidate solution from the internal metamodel without evaluating it:
- First line: the bare verb
PREDICTSOLUTION, alone on its line. The engine dispatches on it and reads the arguments from the next line. - Second line:
<modelIdentifier>, optionally followed by<solutionIdentifier>: the ID of a solution the model owns (fromCREATESOLUTIONorCOPYSOLUTION) to predict in place, or-1(or nothing) to predict a new empty solution built from the values that follow. - Following lines: one
<variableName> <variableValue>pair per line for each input variable. - Last line:
END.
PREDICTSOLUTION
<modelIdentifier> <solutionIdentifier>
<variableName1> <variableValue1>
...
<variableNameN> <variableValueN>
END
Return
The full form of the solution reply (see § Solution Replies). The first line echoes <modelIdentifier> and <solutionIdentifier> as sent, with -1 for a new empty solution.
On error (for example, an invalid solution ID), the reply begins with ERROR followed by a description.
Evaluate Solution
Command Format
Several lines, to compute the expressions, constraints and objectives of a solution from client-supplied input and output values, without submitting the solution to the engine:
- First line: the bare verb
EVALUATESOLUTION, alone on its line. The engine dispatches on it and reads the arguments from the next line. - Second line:
<modelIdentifier>, optionally followed by<solutionIdentifier>, with the same meaning as forPREDICTSOLUTION. - Following lines: one
<variableName> <variableValue>pair per line for each input variable and each output variable. - Last line:
END.
EVALUATESOLUTION
<modelIdentifier> <solutionIdentifier>
<variableName1> <variableValue1>
...
<variableNameN> <variableValueN>
END
Return
The full form of the solution reply (see § Solution Replies). The first line echoes <modelIdentifier> and <solutionIdentifier> as sent, with -1 for a new empty solution.
On error (for example, an invalid solution ID), the reply begins with ERROR followed by a description.
Add Solution
Command Format
Several lines, to add a suggested, required or evaluated solution to a model:
- First line: the bare verb
ADDSOLUTION, alone on its line. The engine dispatches on it and reads the arguments from the next line. - Second line:
<modelIdentifier>,<solutionIdentifier>(the ID of a solution the model owns, or-1to add a new solution built from the values that follow), and two boolean flags,<isEvaluated>and<ignoreMapping>. A three-token form without<solutionIdentifier>is also accepted. The flags are the literalstrueorfalse, not0and1. The server reads them with Java’sBoolean.parseBoolean, which givestrueonly for the texttrue(case-insensitive) and silently treats every other token, including1, asfalse.false false: a suggested solution (input values only). The engine can change the input values so that they satisfy the input-only constraints and the rules of each variable type. This is the equivalent ofAddSuggested().true true: an evaluated solution (input and output values). This is the equivalent ofAddEvaluated().false true: a required solution (input values only). The engine uses the input values as given. This is the equivalent ofAddRequired().
- Following lines: one
<variableName> <variableValue>pair per line for each input variable and, when<isEvaluated>istrue, each output variable. The value-line rules are the same as forSUBMITSOLUTION: blank lines are ignored, objective and constraint names are accepted and ignored, and any other undeclared name getsERROR BAD VALUE NAME: <name>. - Last line:
END.
ADDSOLUTION
<modelIdentifier> <solutionIdentifier> <isEvaluated> <ignoreMapping>
<variableName1> <variableValue1>
...
<variableNameN> <variableValueN>
END
Return
One line with the number of solutions evaluated so far, as GetNumberOfCompletedIterations() reports it.
On error (for example, an invalid model ID or a missing required value), the reply begins with ERROR followed by a description.
42
Get Solution
Command Format
One line with two integer parameters, <modelIdentifier> and <solutionIdentifier>, to read everything about one solution.
GETSOLUTION <modelIdentifier> <solutionIdentifier>
Return
The full form of the solution reply (see § Solution Replies).
On error (for example, an invalid solution ID), the reply begins with ERROR followed by a description.
Get Best Solutions
Command Format
One line with two integer parameters: <modelIdentifier> and <limit>, the number of best solutions to return. <limit> is ignored for a multi-objective model, which returns the whole Pareto frontier.
GETBESTSOLUTIONS <modelIdentifier> <limit>
Return
The best solutions, one after the other, each in the full form of the solution reply (see § Solution Replies). A line with three dashes and a 0-based counter precedes each solution, including the first.
On error (for example, an invalid model ID), the reply begins with ERROR followed by a description.
--- 0
<solution 1 output>
--- 1
<solution 2 output>
...
--- <n-1>
<solution N output>
Get All Solutions
Command Format
One line with one parameter, <modelIdentifier>.
GETALLSOLUTIONS <modelIdentifier>
Return
Every evaluated solution, one after the other, each in the full form of the solution reply (see § Solution Replies). A line with three dashes and a 0-based counter precedes each solution, including the first.
On error (for example, an invalid model ID), the reply begins with ERROR followed by a description.
--- 0
<solution 1 output>
--- 1
<solution 2 output>
...
--- <n-1>
<solution N output>
Add All Solutions
Command Format
One line with two integer parameters, <destinationModelIdentifier> and <sourceModelIdentifier>.
ADDALLSOLUTIONS <destinationModelIdentifier> <sourceModelIdentifier>
Return
One line with OK on success.
On error (for example, an invalid model ID), the reply begins with ERROR followed by a description.
OK
Copy Solution
Command Format
One line that copies one solution into a model, the engine-side form of CopySolution. It takes four integer parameters: <destinationModelIdentifier>, <sourceModelIdentifier>, <sourceSolutionIdentifier> (the ID of a solution the source model owns, or -1) and <sourceIteration>, which is used when the solution ID is -1: the iteration number of an evaluated solution of the source model, as GETBESTSOLUTIONS and GETALLSOLUTIONS report it. The destination model owns the copy, and the copy has the same values as the source solution for every variable.
COPYSOLUTION <destinationModelIdentifier> <sourceModelIdentifier> <sourceSolutionIdentifier> <sourceIteration>
Return
The short form of the solution reply (see § Solution Replies) for the new copy. Use the returned solution ID with ADDSOLUTION, PREDICTSOLUTION or EVALUATESOLUTION.
On error (for example, an unknown model or solution), the reply begins with ERROR followed by a description.
Get Names
Command Format
One line with one parameter, <modelIdentifier>.
GETNAMES <modelIdentifier>
Return
A count line, <numberOfInputs> <numberOfOutputs>, followed by one name per line: every input name first, then every output name. A variable name cannot contain whitespace, ; or a newline, so one name per line is unambiguous.
The names are the ones the typed API reports. Most variables appear under the name they were added with. Permutations, containers and special purpose variables expand into their generated element names joined by @. The two lists never overlap: the coordinates that the optimizer sets are inputs, and the values the simulation must write are outputs.
On error (for example, an invalid model ID), the reply begins with ERROR followed by a description.
2 1
x1
x2
result
Delete Model
Command Format
One line with one parameter, <modelIdentifier>.
DELETEMODEL <modelIdentifier>
Return
One line with OK. Deleting an identifier the engine no longer holds is not an error, so a client may delete a model twice. An identifier that is not an integer gets ERROR.
OK
Quit
Command Format
One line with no parameters. The server stops and sends no reply.
QUIT
Worked Example
This example defines a model, requests three solutions, evaluates them and reads the best one back. Lines that begin with > are the client’s input on STDIN, and lines that begin with < are the server’s replies on STDOUT.
> CREATEMODEL
> CONTINUOUS X -10 10
> CONTINUOUS Y -15 15
> OUTPUT Z
> CONSTRAINT C1 X<Y
> CONSTRAINT C2 X+Y>1
> CONSTRAINT C3 X+Y<10
> OBJECTIVE O1 MAX X+Y-Z
> END
< 0
> CREATESOLUTION 0
< 0 0
< 1 1 0 0 1 1 0
< X -2.5
< Y 7.75
> SUBMITSOLUTION
> 0 0
> Z 66
> END
< 1
> CREATESOLUTION 0
< 0 1
< 2 1 0 0 1 1 0
< X 0.5
< Y 0.5
> SUBMITSOLUTION
> 0 1
> Z .5
> END
< 2
> CREATESOLUTION 0
< 0 2
< 3 1 0 0 1 1 0
< X -5.0
< Y 15.0
> SUBMITSOLUTION
> 0 2
> Z 250
> END
< 3
> GETBESTSOLUTIONS 0 1
< --- 0
< 2 1 1 1 1 1 0
< X 0.5
< Y 0.5
< Z 0.5
< O1 0.5
< C1 1.0
< C1;LHS;1 0.5
< C1;RHS;1 0.5
< C2 1.0
< C2;LHS;1 1.0
< C2;RHS;1 1.0
< C3 1.0
< C3;LHS;1 1.0
< C3;RHS;1 10.0
> GETALLSOLUTIONS 0
< --- 0
< 2 1 1 1 1 1 0
< X 0.5
< Y 0.5
< Z 0.5
< O1 0.5
< C1 1.0
< C1;LHS;1 0.5
< C1;RHS;1 0.5
< C2 1.0
< C2;LHS;1 1.0
< C2;RHS;1 1.0
< C3 1.0
< C3;LHS;1 1.0
< C3;RHS;1 10.0
< --- 1
< 1 1 1 1 1 1 0
< X -2.5
< Y 7.75
< Z 66.0
< O1 -60.75
< C1 1.0
< C1;LHS;1 -2.5
< C1;RHS;1 7.75
< C2 1.0
< C2;LHS;1 5.25
< C2;RHS;1 1.0
< C3 1.0
< C3;LHS;1 5.25
< C3;RHS;1 10.0
< --- 2
< 3 1 1 1 1 1 0
< X -5.0
< Y 15.0
< Z 250.0
< O1 -240.0
< C1 1.0
< C1;LHS;1 -5.0
< C1;RHS;1 15.0
< C2 1.0
< C2;LHS;1 10.0
< C2;RHS;1 1.0
< C3 1.0
< C3;LHS;1 10.0
< C3;RHS;1 10.0
> DELETEMODEL 0
< OK
> QUIT
QUIT stops the server and sends no reply, so the example ends there.
Migrating from OptQuest 9
This appendix is for users of OptQuest 9. New users can skip it. The examples are in Java, the language in which the OptQuest 9 API was most used, but the OptQuest 10 mappings apply in all five languages (Java, C#, C++, C and Python).
The OptQuest 10 API has built-in parallel execution, so the client manages no threads or queues, and it follows one pattern in every supported language.
Every OptQuest 9 feature maps to an OptQuest 10 call. In OptQuest 9 the central object was COptQuestOptimization. The client subclassed it, overrode virtual methods to define the model, and evaluated solutions through a dependency-injection pattern. In OptQuest 10 the model is an opaque, immutable OptQuestModel, and callbacks evaluate the solutions.
In OptQuest 9 the client created the objects for decision variables, objectives and constraints, managed their lifetimes, and added them to its COptQuestOptimization subclass. In OptQuest 10 the OptQuestModel creates and owns those objects, and the client refers to them by name.
In OptQuest 9 an objective could receive its value directly from the simulation. In OptQuest 10 an objective is always an expression over input and output variables. To reproduce an OptQuest 9 objective that took a simulation result, add an output variable for the result and make the objective’s expression reference it. This replaces a COptQuestUserControlledObjective tied to a simulation output:
//to be collected from the simulation
myModel.AddOutputVariable("simOutput");
//the expression for the objective is just the output value
myModel.AddMinimizeObjective("objective","simOutput");The examples below map the OptQuest 9 API to the OptQuest 10 API.
New Optimization
OptQuest 9
class MyOptimization extends COptQuestOptimization {
//remember to pass into this object a reference
//to all the variables and objectives
public void Evaluate(COptQuestSolution sol)
throws COptQuestException {
double myVarValue = sol.GetVariableValue(myVar);
double myOutputValue = //run my simulation;
sol.SetVariableValue(myOutput, myOutputValue);
}
}
MyOptimization myOpt = new MyOptimization();OptQuest 10
OptQuestModel myModel = new OptQuestModel();Add Decision Variable
OptQuest 9
COptQuestVariable myVar = new COptQuestContinuousVariable(min, max);
myOpt.AddVariable(myVar);OptQuest 10
myModel.AddContinuousVariable("myVar", min, max);Add Output Variable
OptQuest 9
COptQuestVariable myOutput = new COptQuestUserControlledVariable();
myOpt.AddVariable(myOutput);OptQuest 10
myModel.AddOutputVariable("myOutput");Add Single Objective
OptQuest 9
class MyObjective extends
COptQuestUserControlledObjective {
//remember to pass into this object a reference to all the variables and objectives
protected void calculateObjective(Solution sol)
throws COptQuestException {
double myVarValue = sol.GetVariableValue(myVar);
double myOutputValue = sol.GetVariableValue(myOutput);
double myObjValue = myVarValue+myOutputValue;
sol.SetObjectiveValue(myObj, myObjValue);
}
}
COptQuestSingleObjective myObj = new MyObjective();
myObj.SetMinimize();
myOpt.AddObjective(myObj);OptQuest 10
myModel.AddMinimizeObjective("myObj", "myVar + myOutput");Add Multi Objective
OptQuest 9
class MyObjective1 extends COptQuestUserControlledObjective {
//remember to pass into this object a reference to all the variables and objectives
protected void calculateObjective(Solution sol)
throws COptQuestException {
double myVarValue = sol.GetVariableValue(myVar);
double myOutputValue = sol.GetVariableValue(myOutput);
double myObjValue = myVarValue - myOutputValue;
sol.SetObjectiveValue(myObj1, myObjValue);
}
}
class MyObjective2 extends
COptQuestUserControlledObjective {
//remember to pass into this object a reference to all the variables and objectives
protected void calculateObjective(Solution sol)
throws COptQuestException {
double myVarValue = sol.GetVariableValue(myVar);
double myOutputValue = sol.GetVariableValue(myOutput);
double myObjValue = myVarValue / myOutputValue;
sol.SetObjectiveValue(myObj2, myObjValue);
}
}
COptQuestSingleObjective myObj1 = new MyObjective1();
myObj1.SetMinimize();
COptQuestSingleObjective myObj2 = new MyObjective2();
myObj2.SetMaximize();
COptQuestFrontierMultiObjective myMultiObj = new COptQuestFrontierMultiObjective();
myMultiObj.AddObjective(myObj1);
myMultiObj.AddObjective(myObj2);
myOpt.AddObjective(myMultiObj);OptQuest 10
myModel.AddMinimizeObjective("myObj1", "myVar - myOutput");
myModel.AddMaximizeObjective("myObj2", "myVar / myOutput");Add Constraint
OptQuest 9
COptQuestConstraint myConstraint = new COptQuestLEConstraint(5);
myConstraint.AddVariable(myVar, 1);
myConstraint.AddVariable(myOutput, -3);
myOpt.AddConstraint(myConstraint);OptQuest 10
myModel.AddConstraint("myConstraint", "myVar - 3 * myOutput <= 5");Evaluate Solution
OptQuest 9
The evaluation is the Evaluate override of the COptQuestOptimization subclass shown under New Optimization.
OptQuest 10
class MyEvaluator implements IOptQuestEvaluator {
public boolean Evaluate(OptQuestSolution sol) {
double myVarValue=sol.GetValue("myVar");
double myOutputValue = //run simulation here;
sol.SetValue("myOutput",myOutputValue);
return true; //submit this trial; return false to reject it
}
}Run Optimization
OptQuest 9
myOpt.SetMaximumIteration(50);
myOpt.Optimize();OptQuest 10
myModel.Optimize(50, new MyEvaluator());Get Best Solution
OptQuest 9
COptQuestSolution best = myOpt.GetBestSolution();
double myBestVal = best.GetVariableValue(myVar);
double myBestObj = best.GetObjectiveValue(myObj);OptQuest 10
OptQuestSolution best = myModel.GetBestSolutions().get(0);
double myBestVal = best.GetValue("myVar");
double myBestObj = best.GetValue("myObj");Get Pareto Frontier of Solutions
OptQuest 9
for (COptQuestSolution frontier : myOpt.GetParetoFrontier()){
double myBestObj1 = frontier.GetObjectiveValue(myObj1);
double myBestObj2 = frontier.GetObjectiveValue(myObj2);
}OptQuest 10
for (OptQuestSolution frontier : myModel.GetBestSolutions()){
double myBestObj1 = frontier.GetValue("myObj1");
double myBestObj2 = frontier.GetValue("myObj2");
}