Cómo comenzar

En este ejemplo, se muestra cómo compilar, resolver y explorar los resultados de un programa lineal simple (LP) con MathOpt. Puedes encontrar información sobre cómo instalar las herramientas del operador OR en la guía de instalación. Las notas adicionales sobre cómo compilar y ejecutar desde la fuente se aplazan hasta el final.

Compila un modelo de MathOpt

Por lo general, en tu fuente, solo necesitas agregar una única dependencia de MathOpt:

Python

from ortools.math_opt.python import mathopt

C++

#include <iostream>
#include <ostream>

#include "absl/log/check.h"
#include "absl/status/statusor.h"
#include "ortools/base/init_google.h"
#include "ortools/math_opt/cpp/math_opt.h"

El siguiente problema de programación lineal se usa en toda esta guía y se resuelve con GLOP.

$$\begin{aligned} &\max &x + 2 \cdot y\\ &\text{subject to} &x + y &\leq 1.5 \\ &&-1 \leq x &\leq 1.5 \\ &&0 \leq y &\leq 1 \end{aligned}$$

Primero, compila el modelo:

Python

# Build the model.
model = mathopt.Model(name="getting_started_lp")
x = model.add_variable(lb=-1.0, ub=1.5, name="x")
y = model.add_variable(lb=0.0, ub=1.0, name="y")
model.add_linear_constraint(x + y <= 1.5)
model.maximize(x + 2 * y)

C++

// Build the model.
namespace math_opt = ::operations_research::math_opt;
math_opt::Model lp_model("getting_started_lp");
const math_opt::Variable x = lp_model.AddContinuousVariable(-1.0, 1.5, "x");
const math_opt::Variable y = lp_model.AddContinuousVariable(0.0, 1.0, "y");
lp_model.AddLinearConstraint(x + y <= 1.5, "c");
lp_model.Maximize(x + 2 * y);

Resolver e inspeccionar la solución

Luego, establece los parámetros para la resolución. La resolución de modelos de optimización con MathOpt es altamente configurable. Existen parámetros independientes del solucionador (p.ej., habilitar la salida), parámetros específicos del solucionador (p.ej., GlopParameters.optimization_rule), parámetros que dependen de las propiedades del modelo (p.ej., la prioridad de ramificación), una devolución de llamada para los registros del solucionador y una devolución de llamada para supervisar y controlar la optimización. Con el siguiente código, se activan los registros del solucionador.

Python

# Set parameters, e.g. turn on logging.
params = mathopt.SolveParameters(enable_output=True)

C++

// Set parameters, e.g. turn on logging.
math_opt::SolveArguments args;
args.parameters.enable_output = true;

Para resolver el problema con GLOP, el solucionador de LP basado en simplex de Google, usa la función Solve().

Python

# Solve and ensure an optimal solution was found with no errors.
# (mathopt.solve may raise a RuntimeError on invalid input or internal solver
# errors.)
result = mathopt.solve(model, mathopt.SolverType.GLOP, params=params)
if result.termination.reason != mathopt.TerminationReason.OPTIMAL:
    raise RuntimeError(f"model failed to solve: {result.termination}")

C++

// Solve and ensure an optimal solution was found with no errors.
const absl::StatusOr<math_opt::SolveResult> result =
    math_opt::Solve(lp_model, math_opt::SolverType::kGlop, args);
CHECK_OK(result.status());
CHECK_OK(result->termination.EnsureIsOptimal());

Por último, inspecciona el valor objetivo de la solución óptima y los valores de las variables óptimas. Ten en cuenta que, como el motivo de finalización fue óptimo, es seguro suponer que existen estos valores, pero por otros motivos de finalización (por ejemplo, inviable o no delimitado), llamar a estos métodos puede ser CHECK fail (en C++) o raise an exception (en Python).

Python

# Print some information from the result.
print("MathOpt solve succeeded")
print("Objective value:", result.objective_value())
print("x:", result.variable_values()[x])
print("y:", result.variable_values()[y])

C++

// Print some information from the result.
std::cout << "MathOpt solve succeeded" << std::endl;
std::cout << "Objective value: " << result->objective_value() << std::endl;
std::cout << "x: " << result->variable_values().at(x) << std::endl;
std::cout << "y: " << result->variable_values().at(y) << std::endl;

Notas sobre la compilación y ejecución de tu código con Bazel

Si compilas MathOpt desde la fuente con bazel, este ejemplo necesita las siguientes dependencias en el destino de compilación:

Python

"//util/operations_research/math_opt/python:mathopt"

C++

"//util/operations_research/math_opt/cpp:math_opt"
"//util/operations_research/math_opt/solvers:glop_solver"

Para ejecutar tu código, el siguiente comando de Bazel compila y ejecuta tu destino.

Python

bazel run path/to/you:target --with_scip=false --with_cp_sat=false
--with_glpk=false --with_glop=true -- --your_flags

C++

bazel run path/to/you:target -- --your_flags