EXPERIMENTAL: These features are experimental and should not be used in production systems.

The Math Optimization Library (`mathopt`) Reference

This is the reference documentation for the Math Optimization Library.

Module: rel:mathopt

View source
``rel:mathopt``

Building mathematical optimization models and integration of external mathematical optimization solvers within Rel.

variables

View source
``rel:mathopt:variables[R]``

The `rel:mathopt:variables[R]` relation is used to declare variables. This relation takes the following argument:

• `R` - a relation that contains the variables to declare.

The relation `R` must contain triples `(Symbol, String, D)` that represent the variable name, the variable type or bound declaration, and the domain, respectively. The string entry of the triples in `R` must be one of the following:

• `"continuous"` - a continuous variable.
• `"integer"` - an integer variable.
• `"binary"` - a binary variable.
• `"lower_bound"` - a lower bound on a `continuous`, `integer`, or `binary` variable.
• `"upper_bound"` - an upper bound on a `continuous`, `integer`, or `binary` variable.

The domain `D`, a relation or number. If the variable is being declared with `"continuous"`, `"integer"`, or `"binary"`, then `D` must be a relation that contains the domain of the variable. If the variable is being bounded by using the string `"lower_bound"` or `"upper_bound"` variable, then `D` must be a number that represents the bound on the variable. See `rel:mathopt:named_variables` for an example of declaring variables with names inferred by the data used in declaring the variables.

Example:

``````    def model:variables = rel:mathopt:variables[{
// Declare continuous variables with no bounds.
:w, "continuous", range[1, 2, 1];

// Declare continuous variable with a single lower bound.
:x, "continuous", ();
:x, "lower_bound", 0.0;

// Declare binary variables with no bounds.
:y, "binary", range[1, 2, 1];

// Declare integer variables with both lower and upper bounds.
:z, "integer", range[1, 2, 1];
:z, "lower_bound", 0.0;
:z, "upper_bound", 50.0
}]``````

named_variables

View source
``rel:mathopt:named_variables[R]``

The `rel:mathopt:named_variables` relation is used to declare variables with names inferred by the data used in declaring the variables. This relation takes the following argument:

• `R` - a relation that contains the variables to declare.

See `rel:mathopt:variables` for more information on the relation `R`.

export

View source
``rel:mathopt:export[Model, Config]``

Export the `Model` to a file format specified in `Config`. See `rel:mathopt:optimize` for more information on the `Model` relation. The `Config` relation is an optional relation that can be used to override values from `mathopt:SolverConfigDefaults`. Use `{}` when no configuration is needed. See `rel:mathopt:SolverConfigDefaults` for more information on the configuration options and their default values.

Inputs:

• `Model`: a relation with `variables` (created using `rel:mathopt:variables` or `rel:mathopt:named_variables`), an objective function specified by `maximize` (or `minimize`), and `constraints`; the latter two being created by using the `mathopt:Solver:Solve` DSL.
• `Config`: a relation to override values from `mathopt:SolverConfigDefaults`. Use `{}` when no configuration is needed.

Output:

• An opaque binary string containing the result of the solver. Use the `rel:mathopt:extract_result` function to extract detailed information from the result.

Example:

``````// Export the model to a MPS-file format.
def result = rel:mathopt:export[model, { :file_format, "mps" }]

// Extract and output the resulting information.
def output = rel:mathopt:extract_result[result, model:variables]``````

optimize

View source
``rel:mathopt:optimize[Model, Config]``

Optimize the `Model` relation. The model objective function is specified with either `maximize` or `minimize` in `Model` and is created using the `mathopt:Solver:Solve` DSL. The constraints are also created using the `mathopt:Solver:Solve` DSL and must be specified in the `Model` module as `constraints`. The variables of the model are specified with `variables` and must be declared with `rel:mathopt:variables` or `rel:mathopt:named_variables`. The `Config` is an optional relation that can be used to override values from `mathopt:SolverConfigDefaults`. Use `{}` when no configuration is needed.

Inputs:

• `Model`: a relation with `variables` (created using `rel:mathopt:variables` or `rel:mathopt:named_variables`), an objective function specified by `maximize` (or `minimize`), and `constraints`; the latter two being created by using the `mathopt:Solver:Solve` DSL.
• `Config`: a relation to override values from `mathopt:SolverConfigDefaults`. Use `{}` when no configuration is needed.

Output:

• An opaque binary string containing the result of the solver. Use the `rel:mathopt:extract_result` function to extract detailed information from the result.

Example:

``````// Define the data. This is the data that will be used to create the model.
module data
def products    = "bands" ; "coils"
def production_rate   = { ("bands", 200.0) ; ("coils", 140.0) }
def avail       = 40.0
def product_profit = { ("bands", 25.0) ; ("coils", 30.0) }
def product_market_demand = { ("bands", 6000.0) ; ("coils", 4000.0) }
end

@inline
module model
// Bring the mathopt:Solver DSL into scope.
with mathopt:Solver:Solve use sum, foreach, *, ≼, /

// Bring the data into scope.
with data use products, product_profit, product_market_demand, production_rate, avail

// Define the model variables.
def variables = rel:mathopt:variables[
{:x_make, "continuous", (products)};
{:x_make, "lower_bound", 0.0}
]
// Bring the variables into scope.
with variables use x_make

// Define the model objective.
def maximize = sum[product_profit[p] * x_make[p] for p in products] // (the total profit)

// Define the model constraints.
module constraints
def time = sum[(1/production_rate[p]) * x_make[p] for p in products] ≼ avail
def market = foreach[p in products: { x_make[p] ≼ product_market_demand[p] }]
end
end

// Optimize the model.
def result = rel:mathopt:optimize[model, {}]

// Extract the result of the optimization process.
def extracted = rel:mathopt:extract_result[result, model:variables]``````

extract_result

View source
``rel:mathopt:extract_result[Result, Variables]``

Extract detailed information from the result of a call to a mathematical optimization solver (`optimize` or `export`). The result must be a materialized relation.

Inputs:

• `result`: a relation that contains the result of a `rel:mathopt:optimize` or `rel:mathopt:export` call. It must be materialized.
• `Variables`: the relation that declares the model variables, created with `rel:mathopt:variables`.

Output:

• A function from variable keys to the float value assigned by the solver, if any. The keys depend on the variable specification in Variables.

Example:

``````// Optimize the model.
def result = rel:mathopt:optimize[model, {}]

// Extract the result of the optimization process.
def extracted = rel:mathopt:extract_result[result, model:variables]``````

serialize

View source
``rel:mathopt:serialize[Model]``

Serialize a `Model` relation into a mathopt-specific binary format. Validate the correctness of `Model`.

Inputs:

• `Model`: a relation specifying the optimization problem using the `rel:mathopt` DSL.

Required relations:

• `minimize` or `maximize`: definition of the objective.
• `variables`: variables used in the optimization.

Optional relations:

• `constraints`: constraints used in the optimization.
• `config`: configuration for the solver.

Output:

• A binary string containing the serialization result.

Example:

``````module model
with mathopt:Solver:Solve use +, *, =

def variables = rel:mathopt:variables[
{:x, "integer", ()};
{:x, "lower_bound", 0.0};
{:y, "integer", ()}
]

with variables use x,y

def minimize = 2 * x + y

module constraints
def c1 = x + 3 * y = 1
def c2 = x + y >= 1
end

module config
def solver_attributes = "time_limit", 10.0
end
end

def output = rel:mathopt:serialize[model]``````

Module: mathopt:SolverConfigDefaults

View source
``mathopt:SolverConfigDefaults``

`mathopt:SolverConfigDefaults` defines the default values for the configuration parameters used by the `rel:mathopt:optimize` function. These values can be overridden by defining a relation named `config` in the module that calls `rel:mathopt:optimize`. The relation must have the same schema as `mathopt:SolverConfigDefaults`.

solver

View source Set solver backend to be used. Currently `"HiGHS"` (MIP and QP formulations), `"DAQP"` (MIP and QP formulations), and `"Pavito"` (MIQP formulations) are accepted. Support for `"Gurobi"` is planned and under development. The default solver is `"HiGHS"`.

Example:

``````// Override the default solver with the "Pavito" solver.
module config
def solver = "Pavito"
end``````

solver_attributes

View source Key value pairs of solver-specific attributes. These are sent directly to the solver backend. The keys must be strings and the values must be strings, floats, or integers. The specific attributes and values are specified by the solver being used. The default attributes are empty.

Example:

``````// Provide a solution timeout limit and turn off presolve while using `"HiGHS"`.
module config
def solver_attributes = {("time_limit", 60.0); ("presolve", "off")}
end``````

file_format

View source A string specifying the format of the optimization model to be returned as a single string. The available formats are `"lp"`, `"mps"`, `"mof"`, and `"nl"`. The default file format is `"lp"`.

Example:

``````// Override the default file format to be `"mps"`.
module config
def file_format = "mps"
end``````

Module: mathopt:Solver

View source
``mathopt:Solver``

`mathopt:Solver` is a domain-specific language (DSL) designed for specifying mathematical optimization problems. It provides primitives for defining model constraints and model objective functions, as well as operations for mathematical computation and logic.

Module: Solve

View source
``mathopt:Solver:Solve``

The `mathopt:Solver:Solve` module contains functions for defining mathematical and logical operations within an optimization model. These functions translate into solver-compatible operations and are used to define the model’s constraints and objective function.

+

View source
``````mathopt:Solver:Solve:(+)
mathopt:Solver:Solve:(-)
mathopt:Solver:Solve:(*)
mathopt:Solver:Solve:(/)``````

`mathopt:Solver:Solve:(+)`, `mathopt:Solver:Solve:(-)`, `mathopt:Solver:Solve:(*)`, and `mathopt:Solver:Solve:(/)` operators are used to formulate mathematical expressions in the constraints and the objective function of a optimization model.

=

View source
``````mathopt:Solver:Solve:(=)
mathopt:Solver:Solve:(≼)
mathopt:Solver:Solve:(≽)``````

`mathopt:Solver:Solve:(=)`, `mathopt:Solver:Solve:(≼)`, and `mathopt:Solver:Solve:(≽) operators are used to specify the relationships among the variables in the constraints.

∧

View source
``````mathopt:Solver:Solve:(∧)
mathopt:Solver:Solve:(∨)``````

`mathopt:Solver:Solve:(∧)` and `mathopt:Solver:Solve:(∨)` operators are used to combine conditions in constraints.

sum

View source
``mathopt:Solver:Solve:sum[R]``

`mathopt:Solver:Solve:sum[R]` specifies the summation of a variable over a domain relation.

Example:

``````// Bring sum operator into scope.
with mathopt:Solver:Solve use sum

// Summation over a domain relation.
def model:maximize = sum[x[i] for i in domain]``````

foreach

View source
``mathopt:Solver:Solve:foreach[R]``

`mathopt:Solver:Solve:foreach[R]` supports creating constraints by batch by supplying one or more domain relations and relevant conditions.

Example:

``````// Bring foreach operator into scope.
with mathopt:Solver:Solve use foreach