Le seguenti sezioni presentano un esempio di un problema LP e mostrano come risolverlo. Ecco il problema:
Ingrandisci 3x + 4y
in base ai seguenti vincoli:
x + 2y
≤ 143x - y
≥ 0x - y
≤ 2
Sia la funzione obiettivo, 3x + 4y
, sia i vincoli sono dati da espressioni lineari, il che rende questo un problema lineare.
I vincoli definiscono l'area consentita, ovvero il triangolo mostrato di seguito, compreso il suo interno.
Passaggi di base per risolvere un problema relativo a LP
Per risolvere un problema di LP, il tuo programma deve includere i seguenti passaggi:
- Importa il wrapper del risolutore lineare,
- dichiarare il risolutore LP,
- a definire le variabili,
- definiscono i vincoli,
- definiscono l'obiettivo,
- chiama il risolutore LP; e
- visualizza la soluzione
Soluzione che utilizza MPSolver
La seguente sezione presenta un programma che risolve il problema utilizzando il wrapper MPSolver e un risolutore LP.
Nota: Per eseguire il programma seguente, devi installare OR-Tools.
Il principale risolutore di ottimizzazione lineare OR-Tools è Glop, il risolutore di programmazione lineare interno di Google. È veloce, efficiente in termini di memoria e numericamente stabile.
Importa il wrapper del risolutore lineare
Importa (o includi) il wrapper per il risolutore lineare OR-Tools, un'interfaccia per i risolutori MIP e lineari, come mostrato di seguito.
Python
from ortools.linear_solver import pywraplp
C++
#include <iostream> #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;
Dichiara il risolutore LP
MPsolver
è un wrapper per diversi risolutori, incluso Glop. Il codice seguente dichiara il risolutore GLOP.
Python
solver = pywraplp.Solver.CreateSolver("GLOP") if not solver: return
C++
std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("SCIP")); if (!solver) { LOG(WARNING) << "SCIP solver unavailable."; return; }
Java
MPSolver solver = MPSolver.createSolver("GLOP");
C#
Solver solver = Solver.CreateSolver("GLOP"); if (solver is null) { return; }
Nota: sostituisci PDLP
con GLOP
per usare un risolutore LP alternativo. Per ulteriori dettagli sulla scelta dei risolutori, consulta Risoluzione avanzata della pagina di destinazione e, per l'installazione di risolutori di terze parti, consulta la guida all'installazione.
Crea le variabili
Innanzitutto, crea le variabili x e y i cui valori siano compresi nell'intervallo da 0 a infinito.
Python
x = solver.NumVar(0, solver.infinity(), "x") y = solver.NumVar(0, solver.infinity(), "y") print("Number of variables =", solver.NumVariables())
C++
const double infinity = solver->infinity(); // x and y are non-negative variables. 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; // x and y are continuous non-negative variables. 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#
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());
Definisci i vincoli
Quindi, definisci i vincoli per le variabili. Assegna un nome univoco a ciascun vincolo (ad esempio constraint0
), quindi definisci i coefficienti del vincolo.
Python
# Constraint 0: x + 2y <= 14. solver.Add(x + 2 * y <= 14.0) # Constraint 1: 3x - y >= 0. solver.Add(3 * x - y >= 0.0) # Constraint 2: x - y <= 2. solver.Add(x - y <= 2.0) print("Number of constraints =", solver.NumConstraints())
C++
// x + 2*y <= 14. MPConstraint* const c0 = solver->MakeRowConstraint(-infinity, 14.0); c0->SetCoefficient(x, 1); c0->SetCoefficient(y, 2); // 3*x - y >= 0. MPConstraint* const c1 = solver->MakeRowConstraint(0.0, infinity); c1->SetCoefficient(x, 3); c1->SetCoefficient(y, -1); // x - y <= 2. MPConstraint* const c2 = solver->MakeRowConstraint(-infinity, 2.0); c2->SetCoefficient(x, 1); c2->SetCoefficient(y, -1); LOG(INFO) << "Number of constraints = " << solver->NumConstraints();
Java
// x + 2*y <= 14. MPConstraint c0 = solver.makeConstraint(-infinity, 14.0, "c0"); c0.setCoefficient(x, 1); c0.setCoefficient(y, 2); // 3*x - y >= 0. MPConstraint c1 = solver.makeConstraint(0.0, infinity, "c1"); c1.setCoefficient(x, 3); c1.setCoefficient(y, -1); // x - y <= 2. MPConstraint c2 = solver.makeConstraint(-infinity, 2.0, "c2"); c2.setCoefficient(x, 1); c2.setCoefficient(y, -1); System.out.println("Number of constraints = " + solver.numConstraints());
C#
// x + 2y <= 14. solver.Add(x + 2 * y <= 14.0); // 3x - y >= 0. solver.Add(3 * x - y >= 0.0); // x - y <= 2. solver.Add(x - y <= 2.0); Console.WriteLine("Number of constraints = " + solver.NumConstraints());
Definire la funzione obiettivo
Il codice seguente definisce la funzione dell'obiettivo, 3x + 4y
, e specifica che questo è un problema di massimizzazione.
Python
# Objective function: 3x + 4y. solver.Maximize(3 * x + 4 * y)
C++
// Objective function: 3x + 4y. MPObjective* const objective = solver->MutableObjective(); objective->SetCoefficient(x, 3); objective->SetCoefficient(y, 4); objective->SetMaximization();
Java
// Maximize 3 * x + 4 * y. MPObjective objective = solver.objective(); objective.setCoefficient(x, 3); objective.setCoefficient(y, 4); objective.setMaximization();
C#
// Objective function: 3x + 4y. solver.Maximize(3 * x + 4 * y);
Richiama il risolutore
Il codice seguente richiama il risolutore.
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();
Visualizza la soluzione
Il codice seguente mostra la soluzione.
Python
if status == pywraplp.Solver.OPTIMAL: print("Solution:") print(f"Objective value = {solver.Objective().Value():0.1f}") print(f"x = {x.solution_value():0.1f}") print(f"y = {y.solution_value():0.1f}") else: print("The problem does not have an optimal solution.")
C++
LOG(INFO) << "Solution:"; LOG(INFO) << "Optimal objective value = " << objective->Value(); LOG(INFO) << x->name() << " = " << x->solution_value(); LOG(INFO) << y->name() << " = " << 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());
I programmi completi
Di seguito sono riportati i programmi completi.
Python
from ortools.linear_solver import pywraplp def LinearProgrammingExample(): """Linear programming sample.""" # Instantiate a Glop solver, naming it LinearExample. solver = pywraplp.Solver.CreateSolver("GLOP") if not solver: return # Create the two variables and let them take on any non-negative value. x = solver.NumVar(0, solver.infinity(), "x") y = solver.NumVar(0, solver.infinity(), "y") print("Number of variables =", solver.NumVariables()) # Constraint 0: x + 2y <= 14. solver.Add(x + 2 * y <= 14.0) # Constraint 1: 3x - y >= 0. solver.Add(3 * x - y >= 0.0) # Constraint 2: x - y <= 2. solver.Add(x - y <= 2.0) print("Number of constraints =", solver.NumConstraints()) # Objective function: 3x + 4y. solver.Maximize(3 * x + 4 * y) # Solve the system. print(f"Solving with {solver.SolverVersion()}") status = solver.Solve() if status == pywraplp.Solver.OPTIMAL: print("Solution:") print(f"Objective value = {solver.Objective().Value():0.1f}") print(f"x = {x.solution_value():0.1f}") print(f"y = {y.solution_value():0.1f}") 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") LinearProgrammingExample()
C++
#include <iostream> #include <memory> #include "ortools/linear_solver/linear_solver.h" namespace operations_research { void LinearProgrammingExample() { 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 non-negative variables. 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(); // x + 2*y <= 14. MPConstraint* const c0 = solver->MakeRowConstraint(-infinity, 14.0); c0->SetCoefficient(x, 1); c0->SetCoefficient(y, 2); // 3*x - y >= 0. MPConstraint* const c1 = solver->MakeRowConstraint(0.0, infinity); c1->SetCoefficient(x, 3); c1->SetCoefficient(y, -1); // x - y <= 2. MPConstraint* const c2 = solver->MakeRowConstraint(-infinity, 2.0); c2->SetCoefficient(x, 1); c2->SetCoefficient(y, -1); LOG(INFO) << "Number of constraints = " << solver->NumConstraints(); // Objective function: 3x + 4y. MPObjective* const objective = solver->MutableObjective(); objective->SetCoefficient(x, 3); objective->SetCoefficient(y, 4); 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) << "Optimal objective value = " << objective->Value(); LOG(INFO) << x->name() << " = " << x->solution_value(); LOG(INFO) << y->name() << " = " << y->solution_value(); } } // namespace operations_research int main(int argc, char** argv) { operations_research::LinearProgrammingExample(); 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; /** Simple linear programming example. */ public final class LinearProgrammingExample { public static void main(String[] args) { Loader.loadNativeLibraries(); MPSolver solver = MPSolver.createSolver("GLOP"); double infinity = java.lang.Double.POSITIVE_INFINITY; // x and y are continuous non-negative variables. MPVariable x = solver.makeNumVar(0.0, infinity, "x"); MPVariable y = solver.makeNumVar(0.0, infinity, "y"); System.out.println("Number of variables = " + solver.numVariables()); // x + 2*y <= 14. MPConstraint c0 = solver.makeConstraint(-infinity, 14.0, "c0"); c0.setCoefficient(x, 1); c0.setCoefficient(y, 2); // 3*x - y >= 0. MPConstraint c1 = solver.makeConstraint(0.0, infinity, "c1"); c1.setCoefficient(x, 3); c1.setCoefficient(y, -1); // x - y <= 2. MPConstraint c2 = solver.makeConstraint(-infinity, 2.0, "c2"); c2.setCoefficient(x, 1); c2.setCoefficient(y, -1); System.out.println("Number of constraints = " + solver.numConstraints()); // Maximize 3 * x + 4 * y. MPObjective objective = solver.objective(); objective.setCoefficient(x, 3); objective.setCoefficient(y, 4); 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"); } private LinearProgrammingExample() {} }
C#
using System; using Google.OrTools.LinearSolver; public class LinearProgrammingExample { static void Main() { Solver solver = Solver.CreateSolver("GLOP"); if (solver is null) { return; } // x and y are continuous non-negative variables. 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()); // x + 2y <= 14. solver.Add(x + 2 * y <= 14.0); // 3x - y >= 0. solver.Add(3 * x - y >= 0.0); // x - y <= 2. solver.Add(x - y <= 2.0); Console.WriteLine("Number of constraints = " + solver.NumConstraints()); // Objective function: 3x + 4y. solver.Maximize(3 * x + 4 * 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"); } }
Soluzione ottimale
Il programma restituisce la soluzione ottimale al problema, come mostrato di seguito.
Number of variables = 2
Number of constraints = 3
Solution:
x = 6.0
y = 4.0
Optimal objective value = 34.0
Ecco un grafico che mostra la soluzione:
La linea verde tratteggiata viene definita impostando la funzione obiettivo su un
valore ottimale di 34. Qualsiasi retta la cui equazione è nella forma 3x + 4y = c
è parallela alla linea tratteggiata e 34 è il valore massimo di c per il quale la retta interseca la regione fattibile.
Per saperne di più sulla risoluzione dei problemi di ottimizzazione lineare, consulta Soluzioni avanzate della pagina di destinazione.