# Primary Optimization Functions

You use DefineOptimization to formulate an optimization, and OptSolution, OptObjective and OptObjectiveSa to view the results, including optimal decisions, and the objective value.

## DefineOptimization()

This function defines an optimization problem. You specify the decision variables, constraints, and objective, if any. It automatically determines the type of optimization: LP, QP, or NLP. If you want to specify a particular type of optimization instead of having Analytica make the choice automatically, use DefineOptimization() with the optional «Type» parameter (see sub-section below).

When DefineOptimization() is evaluated, it returns a reference to a special object, which displays as: «LP», «QP», «QCP», «NCQCP», «NLP», or «NSP», depending on the type of problem. Double click on this object to open a window with the details of the optimization.

DefineOptimization() has a large number of parameters, of which all but the first, Decisions, are optional. It's convenient to use the named-parameter syntax, where you specify each parameter name, followed by a colon (:), followed by the parameter value -- for example:

DefineOptimization(
Decisions: [d1, d2],
Constraints: [c1, c2, c3],
Maximize: x)

Parameters

«Decisions»

The Optimizer searches for the values of these decisions that maximize (or minimize) the Objective and/or meet Constraints. This parameter is a a comma-separated list of identifiers of decision variables -- for example:

DefineOptimization(Decisions: Height, Radius ,...)

You may optionally enclose the list in square brackets .

DefineOptimization(Decisions: [Height, Radius] ,...)

Use All to include all the decision variables in the model, or All in m to include all decision variables in a module, m:

DefineOptimization(Decisions: All,...)
DefineOptimization(Decisions: All in LP_Module,...)

«Constraints»

Type: variable (optional)

Constraints are equality or inequality expressions that any solution must satisfy. You may specify actual constraint expressions or identifiers of Constraints, separated by commas:

DefineOptimization(..., Constraints: [Height_limit, Volume_limit],...)
DefineOptimization(..., Constraints: 4*x + 3*x*y - y^2 >= z^2,...)

You may omit the Constraints parameter for unconstrained optimizations.

Use All to include all constraint nodes in the model, or All in m to include all constraint nodes in a module, m:

DefineOptimization(..., Constraints: All,...)
DefineOptimization(..., Constraints: All in LP_Module,...)

«Minimize»or «Maximize»

Synonyms: «Min» or «Max»

Type: expression (optional)

Use one of these parameter names to identify the Objective variable or expression to minimize or maximize:

DefineOptimization(...,Minimize: Surface_Area,...)
DefineOptimization(...,Minimize: 2*pi*R^2 + 2*pi*R*H,...)

You may omit this parameter if the the goal is simply to find a feasible solution meeting all constraints. In that case, you must include one or more constraints.

The value of the Objective must be scalar for each optimization run. If the Objective evaluates to an array, it performs a separate optimization for each value. For example:

DefineOptimization(..., Maximize: Array(Objective_index, [Profit, Revenue]),...)

will perform two optimizations, to maximize Profit and Revenue respectively, and return the results as an array.

«Guess»

Synonyms: «InitialGuess», «InitialValue»

Type: expression (optional)

Indicates an initial guess for optimization types that may have local minimum. These are only applicable to nonlinear (NLP) type problems. (It is ignored for LP and convex QP optimizations.)

To enter guesses for multiple decision variables, separate them by commas in the same order as the decisions are listed after the «Decisions» parameter:

DefineOptimization(
Decisions: Height, Radius,
Guess: 12, 7)

If you have specified N decisions, you can list up to N guess values (or expressions) separated by commas. The guess values are placed in positional correspondence with the decisions listed — in the example, 12 is used as the guess for Height, 7 as the guess for Radius. You can pass Null for for any guess, in which case the guess obtained from the decision object is not overridden by the parameter, e.g.:

DefineOptimization(
Decisions: Height, Radius,
Guess: Null, 7)

If you specify only one «guess» parameter, it applies to all decisions. In this case, it uses the same guess value to every element of a decision array:

DefineOptimization(Decisions: Decision_Array, Guess: 100)

If you wish to override the guess only for the first parameter, specify the second guess as Null.

When an expression passed to the «guess» parameter evaluates to an array, the array value is used as the guess. Any indexes that are extrinsic to the decision thus result in an array abstraction with multiple optimizations from distinct starting points. Any indexes that are intrinsic to the decision are consumed, specifying an array-valued initial guess.

It is usually simplest to enter a guess as the Initial guess attribute of each Decision variable, rather than providing it as a «guess» parameter to DefineOptimization(). If there are values in both places, the DefineOptimization() «guess» parameter overrides the «Decision» variable’s Initial guess attribute.

«Domain» and «Bounds»

Type: domain expression (optional)

You can use domain expressions to determine variable types and bounds. When used as a parameter in DefineOptimization, the expression follows the word «Domain» as in these examples:

When only one domain specification is listed, it applies to all decision variables. In this example, the domain parameter overrides the domain of both Height and Radius to force a continuous optimization with a lower bound of zero:

DefineOptimization(
Decisions: Height, Radius,
Domain: Continuous(LB: 0),
...)

When you have listed N decisions, you may list up to N domain specifications, which apply in positional correspondence with the decisions:

DefineOptimization(
Decisions: Height, Radius,
Domain: Integer(LB: 0), Continuous(LB: 0, UB: 5),
...)

Use Null when you do not wish to override the domain for one decision while specifying the domain for others. E.g., to override only the domain for Radius:

DefineOptimization(
Decisions: Height, Radius,
Domain: Null, Continuous(LB: 0, UB: 5),
...)

Note: The only way to specify the integer type and bounds for a local variable that used as a decision variable is by using the domain parameter.

For details on Domain expression syntax, see Domain and Bounds section in the Optimizer Attributes chapter.

Unless you have a specific reason to enter domains and bounds as a DefineOptimization() parameter, it is recommended to enter them into the Decision’s Domain attributes instead. When domain specifications exist in both locations, the DefineOptimization() parameter takes precedence.

«Type»

Type: text (optional)

Indicates the type of optimization problem. If omitted, Analytica analyzes the decisions, objective, and constraints to determine the problem type automatically. This parameter is useful if you expect a particular type of optimization (LP, for example) and you want it to give a warning if the model characteristics don’t match your expectation — for example, if an expected LP has non-linear characteristics. Type setting can also affect the choice of engine and processing speed.

Quotation marks must be included since this parameter is passed as text.

Example:

DefineOptimization(...,Type: "QP")

Possible «Type» values are:

• LP: Linear Program
Optimization is limited to linear programs only. An error will display if the optimization has any non-linear characteristics.
• QP: Linearly Constrained Quadratic Program
Most restrictive QP category. It displays an error if constraints are not linear.
• QCP: Quadratically Constrained Program
Solution set may be non-convex. The solution may depend on initial guess.Optimizer will spend some processing time evaluating convexity characteristics.
• NCQCP: Non-Convex Quadratically Constrained Program
Least restrictive QP category. Solution set may be non-convex. Optimum solution may depend on initial guess. Faster than QCP setting for non-convex problems since the optimizer will not spend time evaluating convexity characteristics. May be slower than QCP setting for convex solution sets.
• NLP: Non-linear Program
Smooth non-linear program. Optimization uses gradient and Jacobian based strategies that assume continuous functions.
• NSP: Non-smooth Program
Selects the Evolutionary engine. Suitable for:
1. Hard integer problems for which non-integer values cannot be computed or are not meaningful
2. Problems with discontinuous relationships between decisions and solutions.

«SetContext»

Type: variable list (optional)

«SetContext» avoids unnecessary computation when solving non-linear programs (NLPs) with extrinsic indexes present in the model. An extrinsic index is an index along which multiple individual optimizations are performed. For any given optimization run, only a single element of the index is relevant. As the optimization engine runs repeatedly reevaluates your model at different search points, arrays indexed by extrinsic indexes will be repeatedly recomputed. Since only one element of an extrinsic index is relevant, all but a single slice of the array will be discarded by the optimization engine. This inefficiency can prolong NLP computation times by orders of magnitude. If more than one extrinsic index is involved, the computational inefficiency could scale quadratically or cubically, etc. with the size of the indexes.

This inefficiency can be avoided by listing a set of context variables after the «SetContext» parameter. When an optimization begins, the full value of the context variable is replaced with just the slice corresponding to the coordinates of the optimization that is active. When used appropriately, this prevents the extrinsic index from being propagated downstream from the context variable, and thus saves unnecessary computation.

The best context variable candidates are arrays that include extrinsic indexes and are computed only once for the optimization (i.e. they are not downstream of a «Decision» variable). Variables for which context is set will not propagate extrinsic indexes to downstream arrays during optimization. The set of context variables should be inclusive enough eliminate extrinsic indexes from every downstream array that is repeatedly evaluated during the optimization (i.e. every array positioned in the influence stream between a «Decision» variable and the Optimization node). But the set should not include the repeatedly evaluated arrays themselves.

Example:

DefineOptimization(...,
SetContext: Base_demand, Price_elasticity, Discount_rate)

'«Engine»:

Type: text (optional)

Usually, the Optimizer chooses a solver engine to match the problem type. But, you can use this parameter to specify which engine you want to use. To see a list of installed engines, evaluate the expression OptEngineInfo('All', 'Name').

Quotation marks must be included since this parameter is passed as text.

Example:

DefineOptimization(..., Engine: "GRG Nonlinear")

Standard Engines:

The following engines come standard with Analytica Optimizer:

• LP/Quadratic
The LP/Quatratic engine handles linear programs and quadratic programs with linear constraints. It implements Primal and Dual Simplex methods plus a Quadratic extension. Memory is efficiently managed using a sparse representation of the LP simplex matrix. For integer domains, the engine first computes a continuous solution, then uses a Branch and Cut method to find the best integer solution. The number of decision variables is limited to 8,000 or less.
• SOCP Barrier
This engine uses a Second Order Cone Programming technique designed specifically for quadratically constrained convex problems. The GRG Nonlinear engine is often a good alternative for this type of problem, especially if the constraints end up being non-convex. The number of decision variables is limited to 2,000 or less.
• GRG Nonlinear
The Generalized Reduced Gradient nonlinear engine is suitable for problems that are relatively smooth with few local optima. Problems that allow gradients and Jacobians to be computed analytically will run much faster than problems that require finite difference methods. The number of decision variables is limited to 500 or less.
• Evolutionary
The Evolutionary engine is the best choice for problems that do not allow non-integer values to be explored during the intermediate steps of a search. These include hard integer problems and problems with a large number of discontinuities. The number of decision variables is limited to 500 or less.

• Large-Scale LP/QP
Allows an unlimited number of variables and constraints. It has been used to solve problems with millions of variables.
• Large-Scale SQP
The most versatile solver for large scale problems. Handles linear, quadratic, conic, smooth nonlinear, and non-smooth problems with no fixed limits on problem size.
• Large-Scale GRG Solver
Extends the variable limit of the GRG nonlinear engine to 12,000 decision variables. It uses sparse matrix storage methods for memory efficiency, and advanced methods for selecting a basis and dealing with degeneracy.
• Gurobi
Gurobi is the fastest available engine for linear and mixed-integer linear (LP/MIP) problems and also handles QP. It has been engineered to expliot multi-core processors more effectively than other solvers.
• XPRESS
XPRESS is designed for high-speed performance on standard LP and mixed-integer linear and quadratic problems (LP/MIP and QP/MIP). It has no fixed limit on the numbers of variables or constraints.
• MOSEK
MOSEK handles large scale LP and QP problems including those with quadratic and second order cone constraints with speed comparable to linear problems. It inclues both simplex and self-dual interior point methods. Also handles convex nonlinear problems. It has no fixed limit on problem size.
• KNITRO
KNITRO is designed especially for smooth nonlinear problems. It includes state-of-the-art implementation of interior point nonlinear methods and "active set" Sequential Linear / Quadratic Programming techniques (SLQP). It has no fixed limit on problem size.
• OptQuest
OptQuest is designed to work will all types of models including those with discontinuous functions. It uses advanced methods including tabu search and scatter search to identify solutions that are globally optimum or close to globally optimum. Supports up to 5,000 variables and 1,000 constraints, though the practical size of problems that can be solved to near global optimality may be less than these limits.

«Over»

Type: index list (optional)

The «Over» parameter forces array abstraction over an index, resulting in separate optimization runs for each element of the index. To abstract over multiple indexes, enter a list of index identifiers separated by commas.

Example:

DefineOptimization(...,Over: Scenario_Index, Objective_Index,...)

«TraceFile»

Type: text (optional)

Creates a trace file containing details about the optimization process. Including the file path is optional. The file will appear in the CurrentDataDirectory, usually the same directory as the model unless changed, if you omit the path.

«TraceFile» can be extremely helpful when debugging convergence issues, i.e., why didn’t the optimization find a solution, or didn’t find the solution I expected it to find?

Examples:

DefineOptimization(..., TraceFile: "c:\ana_models\mytracefile.log")
DefineOptimization(..., TraceFile: "mytracefile.log")

The traceFile is written only when a model is solved by an algorithm that repeatedly evaluates the model, which generally means that a non-linear search algorithm must be used. The «TraceFile» parameter is ignored when solving linear or quadratic problems via simplex or Barrier methods.

Tip

To produce a traceFile for a linear or quadratic problem, specify Engine:"GRG Nonlinear" to force the use of a non-linear search algorithm. Remove this setting once you’ve finished your debugging.

«Engine Settings»

Type: text (optional)

Each optimizer engine has a list of setting commands. You can pass setting commands to the optimizer engine using the «Parameter» and «Setting» parameters. These are text values that must be enclosed in quotation marks.

See Control Settings chapter for details on available settings.

You can set parameters for the optimization engine using the following syntax:

SettingName: "setting_name", SettingValue: setting_value

The parameter name and setting name must be inside quotes since they are text strings passed directly to the optimization engine. To change more than one setting, «SettingName» and «SettingValue» must be arrays that have exactly one common index.

See Control Settings chapter for a full list of available settings and value ranges.

## OptSolution(Opt, Decision, PassNonFeasible)

The OptSolution() function causes the optimization problem to be solved and returns optimized values of the decision variables. Analytica does not change the values of the input decision nodes, nor does it reveal the optimization results when you evaluate the optimization node.

Parameters

«Opt»

Type: variable

Identifies the node defined using DefineOptimization().

«Decision»

Type: variable (optional)

The Decision parameter identifies the decision input node containing the desired values. If you omit the «Decision» parameter, OptSolution lists all scalar decision variables as a flattened 1-D array using .DecisionVector as an local index.

If you have more than one decision node, it is usually convenient to have a separate OptSolution counterpart for each input node. This way, your optimized results will be in the same format as the input decision nodes.

«PassNonFeasible»

Type: boolean (optional)

If omitted or set to 0 (FALSE) OptSolution() will be Null if no feasible solution is found. When set to 1 (TRUE), OptSolution() will return the last computed solution before infeasibility was determined.

## OptObjective(Opt, PassNonFeasible)

This function tries to solve the optimization problem Opt (if it hasn't been solved) and returns the optimized (minimum or maximum) value of the objective. If multiple optimizations are performed, OptObjective returns an array along extrinsic indexes.

Parameters

«Opt»: (Type: variable) This should be the name of the variable defined with DefineOptimization().

«PassNonFeasible» : (Type: boolean (optional)). If omitted or set to 0 (FALSE), function OptObjective() returns Null if no feasible solution is found. When set to 1 (TRUE), it returns the objective value corresponding to the last computed solution before it determined the problem is infeasible.

## OptObjectiveSa(Opt, Decision)

For LP problems only. Performs sensitivity analysis on objective value relative to decision variables. The optimal solution for an LP occurs at the intersection of some subset of constraints, which is a vertex in the simplex of feasible solutions. This set of constraints is often referred to as the basis of the solution. If we were to increase or decrease one linear objective coefficient slightly, the value of the objective would change, of course, but over some range of values the optimal solution would remain at the same vertex (basis). OptObjectiveSa() computes the the range (i.e., lower and upper limit) over which each linear objective coefficient can be changed without causing a change in the basis for the optimal solution. The result is indexed by a local index .Range having values ["lower","upper"].

Parameters

«Opt»

Type: variable

Identifies the object defined using DefineOptimization().

«Decision»

Type: variable (optional)

If Omitted, the function will return sensitivities for relative to all scalar decision variables flattened into a 1-D local index named .DecisionVector. If the «Decision» parameter is included, it will return sensitivities for that decision with the same dimensionality as the decision along with the .Range index.