W sekcjach poniżej znajdziesz przykładowy problem MIP i sposób jego rozwiązania. Problem jest taki:
Maksymalizuj wartość x + 10y pod warunkiem, że:
x + 7y≤ 17,5- 0 ≤
x≤ 3,5 - 0 ≤
y x,yliczby całkowite
Ponieważ ograniczenia są liniowe, jest to po prostu liniowy problem optymalizacji, w którym rozwiązania muszą być liczbami całkowitymi. Poniższy wykres przedstawia całkowite punkty w regionie możliwym do rozwiązania problemu.

Zwróć uwagę, że ten problem jest bardzo podobny do zadania optymalizacji liniowej opisanego w artykule Rozwiązywanie problemu dotyczącego strony docelowej, ale w tym przypadku rozwiązania muszą być liczbami całkowitymi.
Podstawowe kroki rozwiązywania problemu MIP
Aby rozwiązać problem MIP, program powinien obejmować następujące elementy:
- Zaimportuj opakowanie rozwiązania liniowego,
- deklarować rozwiązanie MIP,
- zdefiniować zmienne,
- zdefiniuj ograniczenia,
- określić cel,
- należy wywołać rozwiązanie MIP,
- wyświetl rozwiązanie
Rozwiązanie przy użyciu funkcji MPSolver
W tej sekcji przedstawimy program, który rozwiązuje problem za pomocą otoki MPSolver i mechanizmu MIP.
Domyślnym rozwiązaniem do rozwiązywania problemów LUB-Tools MIP jest SCIP.
Importowanie kodu rozwiązania liniowego
Zaimportuj (lub uwzględnij) kod rozwiązań liniowych OR-Tools (czyli interfejs do rozwiązań MIP) i rozwiązań liniowych, jak pokazano poniżej.
Python
from ortools.linear_solver import pywraplp
C++
#include <memory> #include "ortools/linear_solver/linear_solver.h"
Java
import com.google.ortools.Loader; import com.google.ortools.linearsolver.MPConstraint; import com.google.ortools.linearsolver.MPObjective; import com.google.ortools.linearsolver.MPSolver; import com.google.ortools.linearsolver.MPVariable;
C#
using System; using Google.OrTools.LinearSolver;
Deklarowanie rozwiązania MIP
Poniższy kod deklaruje rozwiązanie MIP zadania. W tym przykładzie korzystamy z rozwiązania SCIP innej firmy.
Python
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver("SAT")
if not solver:
return
C++
// Create the mip solver with the SCIP backend.
std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("SCIP"));
if (!solver) {
LOG(WARNING) << "SCIP solver unavailable.";
return;
}
Java
// Create the linear solver with the SCIP backend.
MPSolver solver = MPSolver.createSolver("SCIP");
if (solver == null) {
System.out.println("Could not create solver SCIP");
return;
}
C#
// Create the linear solver with the SCIP backend.
Solver solver = Solver.CreateSolver("SCIP");
if (solver is null)
{
return;
}
Zdefiniuj zmienne
W poniższym kodzie zdefiniowano zmienne występujące w zadaniu.
Python
infinity = solver.infinity()
# x and y are integer non-negative variables.
x = solver.IntVar(0.0, infinity, "x")
y = solver.IntVar(0.0, infinity, "y")
print("Number of variables =", solver.NumVariables())
C++
const double infinity = solver->infinity(); // x and y are integer non-negative variables. MPVariable* const x = solver->MakeIntVar(0.0, infinity, "x"); MPVariable* const y = solver->MakeIntVar(0.0, infinity, "y"); LOG(INFO) << "Number of variables = " << solver->NumVariables();
Java
double infinity = java.lang.Double.POSITIVE_INFINITY;
// x and y are integer non-negative variables.
MPVariable x = solver.makeIntVar(0.0, infinity, "x");
MPVariable y = solver.makeIntVar(0.0, infinity, "y");
System.out.println("Number of variables = " + solver.numVariables());
C#
// x and y are integer non-negative variables.
Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y");
Console.WriteLine("Number of variables = " + solver.NumVariables());
Program wykorzystuje metodę MakeIntVar (lub wariant w zależności od języka kodowania) do tworzenia zmiennych x i y, które przyjmują wartości nieujemne liczby całkowite.
Zdefiniuj ograniczenia
Poniższy kod definiuje ograniczenia tego problemu.
Python
# x + 7 * y <= 17.5.
solver.Add(x + 7 * y <= 17.5)
# x <= 3.5.
solver.Add(x <= 3.5)
print("Number of constraints =", solver.NumConstraints())
C++
// x + 7 * y <= 17.5. MPConstraint* const c0 = solver->MakeRowConstraint(-infinity, 17.5, "c0"); c0->SetCoefficient(x, 1); c0->SetCoefficient(y, 7); // x <= 3.5. MPConstraint* const c1 = solver->MakeRowConstraint(-infinity, 3.5, "c1"); c1->SetCoefficient(x, 1); c1->SetCoefficient(y, 0); LOG(INFO) << "Number of constraints = " << solver->NumConstraints();
Java
// x + 7 * y <= 17.5.
MPConstraint c0 = solver.makeConstraint(-infinity, 17.5, "c0");
c0.setCoefficient(x, 1);
c0.setCoefficient(y, 7);
// x <= 3.5.
MPConstraint c1 = solver.makeConstraint(-infinity, 3.5, "c1");
c1.setCoefficient(x, 1);
c1.setCoefficient(y, 0);
System.out.println("Number of constraints = " + solver.numConstraints());
C#
// x + 7 * y <= 17.5.
solver.Add(x + 7 * y <= 17.5);
// x <= 3.5.
solver.Add(x <= 3.5);
Console.WriteLine("Number of constraints = " + solver.NumConstraints());
Określ cel
Poniższy kod definiuje element objective function problemu.
Python
# Maximize x + 10 * y. solver.Maximize(x + 10 * y)
C++
// Maximize x + 10 * y. MPObjective* const objective = solver->MutableObjective(); objective->SetCoefficient(x, 1); objective->SetCoefficient(y, 10); objective->SetMaximization();
Java
// Maximize x + 10 * y. MPObjective objective = solver.objective(); objective.setCoefficient(x, 1); objective.setCoefficient(y, 10); objective.setMaximization();
C#
// Maximize x + 10 * y. solver.Maximize(x + 10 * y);
Wywoływanie rozwiązania
Ten kod wywołuje funkcję rozwiązania.
Python
print(f"Solving with {solver.SolverVersion()}")
status = solver.Solve()
C++
const MPSolver::ResultStatus result_status = solver->Solve();
// Check that the problem has an optimal solution.
if (result_status != MPSolver::OPTIMAL) {
LOG(FATAL) << "The problem does not have an optimal solution!";
}
Java
final MPSolver.ResultStatus resultStatus = solver.solve();
C#
Solver.ResultStatus resultStatus = solver.Solve();
Wyświetl rozwiązanie
Poniższy kod wyświetla rozwiązanie.
Python
if status == pywraplp.Solver.OPTIMAL:
print("Solution:")
print("Objective value =", solver.Objective().Value())
print("x =", x.solution_value())
print("y =", y.solution_value())
else:
print("The problem does not have an optimal solution.")
C++
LOG(INFO) << "Solution:"; LOG(INFO) << "Objective value = " << objective->Value(); LOG(INFO) << "x = " << x->solution_value(); LOG(INFO) << "y = " << y->solution_value();
Java
if (resultStatus == MPSolver.ResultStatus.OPTIMAL) {
System.out.println("Solution:");
System.out.println("Objective value = " + objective.value());
System.out.println("x = " + x.solutionValue());
System.out.println("y = " + y.solutionValue());
} else {
System.err.println("The problem does not have an optimal solution!");
}
C#
// Check that the problem has an optimal solution.
if (resultStatus != Solver.ResultStatus.OPTIMAL)
{
Console.WriteLine("The problem does not have an optimal solution!");
return;
}
Console.WriteLine("Solution:");
Console.WriteLine("Objective value = " + solver.Objective().Value());
Console.WriteLine("x = " + x.SolutionValue());
Console.WriteLine("y = " + y.SolutionValue());
Oto rozwiązanie problemu.
Number of variables = 2 Number of constraints = 2 Solution: Objective value = 23 x = 3 y = 2
Optymalna wartość funkcji celu wynosi 23 i występuje w punkcie x = 3 y = 2.
Ukończ programy
Oto pełne programy.
Python
from ortools.linear_solver import pywraplp
def main():
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver("SAT")
if not solver:
return
infinity = solver.infinity()
# x and y are integer non-negative variables.
x = solver.IntVar(0.0, infinity, "x")
y = solver.IntVar(0.0, infinity, "y")
print("Number of variables =", solver.NumVariables())
# x + 7 * y <= 17.5.
solver.Add(x + 7 * y <= 17.5)
# x <= 3.5.
solver.Add(x <= 3.5)
print("Number of constraints =", solver.NumConstraints())
# Maximize x + 10 * y.
solver.Maximize(x + 10 * y)
print(f"Solving with {solver.SolverVersion()}")
status = solver.Solve()
if status == pywraplp.Solver.OPTIMAL:
print("Solution:")
print("Objective value =", solver.Objective().Value())
print("x =", x.solution_value())
print("y =", y.solution_value())
else:
print("The problem does not have an optimal solution.")
print("\nAdvanced usage:")
print(f"Problem solved in {solver.wall_time():d} milliseconds")
print(f"Problem solved in {solver.iterations():d} iterations")
print(f"Problem solved in {solver.nodes():d} branch-and-bound nodes")
if __name__ == "__main__":
main()
C++
#include <memory>
#include "ortools/linear_solver/linear_solver.h"
namespace operations_research {
void SimpleMipProgram() {
// Create the mip solver with the SCIP backend.
std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("SCIP"));
if (!solver) {
LOG(WARNING) << "SCIP solver unavailable.";
return;
}
const double infinity = solver->infinity();
// x and y are integer non-negative variables.
MPVariable* const x = solver->MakeIntVar(0.0, infinity, "x");
MPVariable* const y = solver->MakeIntVar(0.0, infinity, "y");
LOG(INFO) << "Number of variables = " << solver->NumVariables();
// x + 7 * y <= 17.5.
MPConstraint* const c0 = solver->MakeRowConstraint(-infinity, 17.5, "c0");
c0->SetCoefficient(x, 1);
c0->SetCoefficient(y, 7);
// x <= 3.5.
MPConstraint* const c1 = solver->MakeRowConstraint(-infinity, 3.5, "c1");
c1->SetCoefficient(x, 1);
c1->SetCoefficient(y, 0);
LOG(INFO) << "Number of constraints = " << solver->NumConstraints();
// Maximize x + 10 * y.
MPObjective* const objective = solver->MutableObjective();
objective->SetCoefficient(x, 1);
objective->SetCoefficient(y, 10);
objective->SetMaximization();
const MPSolver::ResultStatus result_status = solver->Solve();
// Check that the problem has an optimal solution.
if (result_status != MPSolver::OPTIMAL) {
LOG(FATAL) << "The problem does not have an optimal solution!";
}
LOG(INFO) << "Solution:";
LOG(INFO) << "Objective value = " << objective->Value();
LOG(INFO) << "x = " << x->solution_value();
LOG(INFO) << "y = " << y->solution_value();
LOG(INFO) << "\nAdvanced usage:";
LOG(INFO) << "Problem solved in " << solver->wall_time() << " milliseconds";
LOG(INFO) << "Problem solved in " << solver->iterations() << " iterations";
LOG(INFO) << "Problem solved in " << solver->nodes()
<< " branch-and-bound nodes";
}
} // namespace operations_research
int main(int argc, char** argv) {
operations_research::SimpleMipProgram();
return EXIT_SUCCESS;
}
Java
package com.google.ortools.linearsolver.samples;
import com.google.ortools.Loader;
import com.google.ortools.linearsolver.MPConstraint;
import com.google.ortools.linearsolver.MPObjective;
import com.google.ortools.linearsolver.MPSolver;
import com.google.ortools.linearsolver.MPVariable;
/** Minimal Mixed Integer Programming example to showcase calling the solver. */
public final class SimpleMipProgram {
public static void main(String[] args) {
Loader.loadNativeLibraries();
// Create the linear solver with the SCIP backend.
MPSolver solver = MPSolver.createSolver("SCIP");
if (solver == null) {
System.out.println("Could not create solver SCIP");
return;
}
double infinity = java.lang.Double.POSITIVE_INFINITY;
// x and y are integer non-negative variables.
MPVariable x = solver.makeIntVar(0.0, infinity, "x");
MPVariable y = solver.makeIntVar(0.0, infinity, "y");
System.out.println("Number of variables = " + solver.numVariables());
// x + 7 * y <= 17.5.
MPConstraint c0 = solver.makeConstraint(-infinity, 17.5, "c0");
c0.setCoefficient(x, 1);
c0.setCoefficient(y, 7);
// x <= 3.5.
MPConstraint c1 = solver.makeConstraint(-infinity, 3.5, "c1");
c1.setCoefficient(x, 1);
c1.setCoefficient(y, 0);
System.out.println("Number of constraints = " + solver.numConstraints());
// Maximize x + 10 * y.
MPObjective objective = solver.objective();
objective.setCoefficient(x, 1);
objective.setCoefficient(y, 10);
objective.setMaximization();
final MPSolver.ResultStatus resultStatus = solver.solve();
if (resultStatus == MPSolver.ResultStatus.OPTIMAL) {
System.out.println("Solution:");
System.out.println("Objective value = " + objective.value());
System.out.println("x = " + x.solutionValue());
System.out.println("y = " + y.solutionValue());
} else {
System.err.println("The problem does not have an optimal solution!");
}
System.out.println("\nAdvanced usage:");
System.out.println("Problem solved in " + solver.wallTime() + " milliseconds");
System.out.println("Problem solved in " + solver.iterations() + " iterations");
System.out.println("Problem solved in " + solver.nodes() + " branch-and-bound nodes");
}
private SimpleMipProgram() {}
}
C#
using System;
using Google.OrTools.LinearSolver;
public class SimpleMipProgram
{
static void Main()
{
// Create the linear solver with the SCIP backend.
Solver solver = Solver.CreateSolver("SCIP");
if (solver is null)
{
return;
}
// x and y are integer non-negative variables.
Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x");
Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y");
Console.WriteLine("Number of variables = " + solver.NumVariables());
// x + 7 * y <= 17.5.
solver.Add(x + 7 * y <= 17.5);
// x <= 3.5.
solver.Add(x <= 3.5);
Console.WriteLine("Number of constraints = " + solver.NumConstraints());
// Maximize x + 10 * y.
solver.Maximize(x + 10 * y);
Solver.ResultStatus resultStatus = solver.Solve();
// Check that the problem has an optimal solution.
if (resultStatus != Solver.ResultStatus.OPTIMAL)
{
Console.WriteLine("The problem does not have an optimal solution!");
return;
}
Console.WriteLine("Solution:");
Console.WriteLine("Objective value = " + solver.Objective().Value());
Console.WriteLine("x = " + x.SolutionValue());
Console.WriteLine("y = " + y.SolutionValue());
Console.WriteLine("\nAdvanced usage:");
Console.WriteLine("Problem solved in " + solver.WallTime() + " milliseconds");
Console.WriteLine("Problem solved in " + solver.Iterations() + " iterations");
Console.WriteLine("Problem solved in " + solver.Nodes() + " branch-and-bound nodes");
}
}
Porównanie optymalizacji linearnej i całkowitej
Porównajmy wskazane powyżej rozwiązanie optymalizacji opartej na liczbach całkowitych z rozwiązaniem odpowiedniego problemu z optymalizacją liniową, w którym usunięte są ograniczenia liczby całkowitej. Możesz zgadnąć, że rozwiązanie problemu to punkt liczby całkowitej w możliwym do wykonania regionie najbliżej rozwiązania liniowego, czyli punkt x = 0, y = 2. Ale, jak później zobaczycie,
nie ma tu miejsca.
Możesz łatwo zmodyfikować program w poprzedniej sekcji, aby rozwiązać problem liniowy, wprowadzając te zmiany:
- Zastępowanie rozwiązania MIP
za pomocą rozwiązania LP
Python
# Create the mip solver with the SCIP backend. solver = pywraplp.Solver.CreateSolver("SAT") if not solver: returnC++
// Create the mip solver with the SCIP backend. std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("SCIP")); if (!solver) { LOG(WARNING) << "SCIP solver unavailable."; return; }Java
// Create the linear solver with the SCIP backend. MPSolver solver = MPSolver.createSolver("SCIP"); if (solver == null) { System.out.println("Could not create solver SCIP"); return; }C#
// Create the linear solver with the SCIP backend. Solver solver = Solver.CreateSolver("SCIP"); if (solver is null) { return; }Python
# Create the linear solver with the GLOP backend. solver = pywraplp.Solver.CreateSolver("GLOP") if not solver: returnC++
// Create the linear solver with the GLOP backend. std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("GLOP"));Java
// Create the linear solver with the GLOP backend. MPSolver solver = MPSolver.createSolver("GLOP"); if (solver == null) { System.out.println("Could not create solver SCIP"); return; }C#
// Create the linear solver with the GLOP backend. Solver solver = Solver.CreateSolver("GLOP"); if (solver is null) { return; } - Zastąp zmienne liczb całkowitych
ze zmiennymi ciągłymi
Python
infinity = solver.infinity() # x and y are integer non-negative variables. x = solver.IntVar(0.0, infinity, "x") y = solver.IntVar(0.0, infinity, "y") print("Number of variables =", solver.NumVariables())C++
const double infinity = solver->infinity(); // x and y are integer non-negative variables. MPVariable* const x = solver->MakeIntVar(0.0, infinity, "x"); MPVariable* const y = solver->MakeIntVar(0.0, infinity, "y"); LOG(INFO) << "Number of variables = " << solver->NumVariables();
Java
double infinity = java.lang.Double.POSITIVE_INFINITY; // x and y are integer non-negative variables. MPVariable x = solver.makeIntVar(0.0, infinity, "x"); MPVariable y = solver.makeIntVar(0.0, infinity, "y"); System.out.println("Number of variables = " + solver.numVariables());C#
// x and y are integer non-negative variables. Variable x = solver.MakeIntVar(0.0, double.PositiveInfinity, "x"); Variable y = solver.MakeIntVar(0.0, double.PositiveInfinity, "y"); Console.WriteLine("Number of variables = " + solver.NumVariables());Python
infinity = solver.infinity() # Create the variables x and y. x = solver.NumVar(0.0, infinity, "x") y = solver.NumVar(0.0, infinity, "y") print("Number of variables =", solver.NumVariables())C++
const double infinity = solver->infinity(); // Create the variables x and y. MPVariable* const x = solver->MakeNumVar(0.0, infinity, "x"); MPVariable* const y = solver->MakeNumVar(0.0, infinity, "y"); LOG(INFO) << "Number of variables = " << solver->NumVariables();
Java
double infinity = java.lang.Double.POSITIVE_INFINITY; // Create the variables x and y. MPVariable x = solver.makeNumVar(0.0, infinity, "x"); MPVariable y = solver.makeNumVar(0.0, infinity, "y"); System.out.println("Number of variables = " + solver.numVariables());C#
// Create the variables x and y. Variable x = solver.MakeNumVar(0.0, double.PositiveInfinity, "x"); Variable y = solver.MakeNumVar(0.0, double.PositiveInfinity, "y"); Console.WriteLine("Number of variables = " + solver.NumVariables());
Po wprowadzeniu tych zmian i ponownym uruchomieniu programu otrzymasz takie dane wyjściowe:
Number of variables = 2 Number of constraints = 2 Objective value = 25.000000 x = 0.000000 y = 2.500000
Rozwiązanie problemu liniowego zachodzi w punkcie x = 0 (y = 2.5), gdzie funkcja celu równa się 25. Ten wykres przedstawia rozwiązania problemów
liniowych i całkowitych.

Zwróć uwagę, że rozwiązanie dotyczące liczb całkowitych nie jest zbliżone do rozwiązania liniowego w porównaniu z większością innych punktów całkowitych w możliwym regionie. Rozwiązania problemów z optymalizacją liniową i odpowiadające im problemy z optymalizacją w postaci liczb całkowitych mogą być bardzo odległe. Z tego powodu oba rodzaje problemów wymagają różnych metod rozwiązania.