Nel problema dello zaino, devi creare un pacchetto di articoli con determinati valori e dimensioni (come pesi o volumi), in un container con una capacità massima di Google. Se le dimensioni totali degli articoli superano la capacità, non puoi imballarli tutti. In tal caso, il problema è scegliere un sottoinsieme degli elementi del totale massimo che verrà inserito nel contenitore.
Le sezioni seguenti mostrano come risolvere un problema relativo allo zaino utilizzando OR-Tools.
Esempio
Ecco una rappresentazione grafica di un problema relativo a uno zaino:
Nell'animazione qui sopra, 50
elementi sono pacchettizzati in un cestino. Ogni elemento ha un valore
(il numero sull'elemento) e una ponderazione (circa proporzionale all'area del
).
È stato dichiarato che il bin ha una capacità di 850
e il nostro obiettivo è trovare il set
di articoli che massimizzeranno il valore totale senza superare la capacità.
Le seguenti sezioni descrivono i programmi che risolvono un problema con gli zaini. Per i programmi completi, vedi Programmi completi.
Importa le librerie
Il codice seguente importa le librerie richieste.
Python
from ortools.algorithms.python import knapsack_solver
C++
#include <algorithm> #include <cstdint> #include <iterator> #include <numeric> #include <sstream> #include <vector> #include "ortools/algorithms/knapsack_solver.h"
Java
import com.google.ortools.Loader; import com.google.ortools.algorithms.KnapsackSolver; import java.util.ArrayList;
C#
using System; using Google.OrTools.Algorithms;
crea i dati
Il codice seguente crea i dati per il problema.
Python
values = [ # fmt:off 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312 # fmt:on ] weights = [ # fmt: off [7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13], # fmt: on ] capacities = [850]
C++
std::vector<int64_t> values = { 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312}; std::vector<std::vector<int64_t>> weights = { {7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13}}; std::vector<int64_t> capacities = {850};
Java
final long[] values = {360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312}; final long[][] weights = {{7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13}}; final long[] capacities = {850};
C#
long[] values = { 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312 }; long[,] weights = { { 7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13 } }; long[] capacities = { 850 };
I dati includono:
weights
: un vettore contenente i pesi degli elementi.values
: un vettore contenente i valori degli elementi.capacities
: un vettore con una sola voce, la capacità dello zaino.
Dichiara il risolutore
Il seguente codice dichiara il risolutore a zaino, un risolutore specializzato per problemi con gli zaini.
Python
solver = knapsack_solver.KnapsackSolver( knapsack_solver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "KnapsackExample", )
C++
KnapsackSolver solver( KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "KnapsackExample");
Java
KnapsackSolver solver = new KnapsackSolver( KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "test");
C#
KnapsackSolver solver = new KnapsackSolver( KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "KnapsackExample");
L'opzione KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER
indica al risolutore di
utilizzare l'algoritmo branch and bound per risolvere il problema.
Chiama il risolutore
Il codice seguente chiama il risolutore e stampa la soluzione.
Python
solver.init(values, weights, capacities) computed_value = solver.solve() packed_items = [] packed_weights = [] total_weight = 0 print("Total value =", computed_value) for i in range(len(values)): if solver.best_solution_contains(i): packed_items.append(i) packed_weights.append(weights[0][i]) total_weight += weights[0][i] print("Total weight:", total_weight) print("Packed items:", packed_items) print("Packed_weights:", packed_weights)
C++
solver.Init(values, weights, capacities); int64_t computed_value = solver.Solve(); std::vector<int> packed_items; for (std::size_t i = 0; i < values.size(); ++i) { if (solver.BestSolutionContains(i)) packed_items.push_back(i); } std::ostringstream packed_items_ss; std::copy(packed_items.begin(), packed_items.end() - 1, std::ostream_iterator<int>(packed_items_ss, ", ")); packed_items_ss << packed_items.back(); std::vector<int64_t> packed_weights; packed_weights.reserve(packed_items.size()); for (const auto& it : packed_items) { packed_weights.push_back(weights[0][it]); } std::ostringstream packed_weights_ss; std::copy(packed_weights.begin(), packed_weights.end() - 1, std::ostream_iterator<int>(packed_weights_ss, ", ")); packed_weights_ss << packed_weights.back(); int64_t total_weights = std::accumulate(packed_weights.begin(), packed_weights.end(), int64_t{0}); LOG(INFO) << "Total value: " << computed_value; LOG(INFO) << "Packed items: {" << packed_items_ss.str() << "}"; LOG(INFO) << "Total weight: " << total_weights; LOG(INFO) << "Packed weights: {" << packed_weights_ss.str() << "}";
Java
solver.init(values, weights, capacities); final long computedValue = solver.solve(); ArrayList<Integer> packedItems = new ArrayList<>(); ArrayList<Long> packedWeights = new ArrayList<>(); int totalWeight = 0; System.out.println("Total value = " + computedValue); for (int i = 0; i < values.length; i++) { if (solver.bestSolutionContains(i)) { packedItems.add(i); packedWeights.add(weights[0][i]); totalWeight = (int) (totalWeight + weights[0][i]); } } System.out.println("Total weight: " + totalWeight); System.out.println("Packed items: " + packedItems); System.out.println("Packed weights: " + packedWeights);
C#
solver.Init(values, weights, capacities); long computedValue = solver.Solve(); Console.WriteLine("Optimal Value = " + computedValue);
Il programma prima inizializza il risolutore e poi lo chiama
computed_value = solver.Solve()
.
Il valore totale della soluzione ottimale è computed_value
, che è lo stesso
come peso totale in questo caso. Il programma ottiene quindi gli indici del
gli elementi pacchettizzati nella soluzione come segue:
packed_items = [x for x in range(0, len(weights[0])) if solver.BestSolutionContains(x)]Poiché "solver.BestSolutionContains(x)" restituisce "TRUE" se l'elemento x è incluso nella soluzione, "packed_items" è un elenco degli elementi pacchettizzati ottimali. Analogamente, "packed_weights" sono i pesi degli elementi pacchettizzati. ### Output del programma Ecco l'output del programma.
Total value = 7534 Total weight: 850 Packed items: [0, 1, 3, 4, 6, 10, 11, 12, 14, 15, 16, 17, 18, 19, 21, 22, 24, 27, 28, 29, 30, 31, 32, 34, 38, 39, 41, 42, 44, 47, 48, 49] Packed_weights: [7, 0, 22, 80, 11, 59, 18, 0, 3, 8, 15, 42, 9, 0, 47, 52, 26, 6, 29, 84, 2, 4, 18, 7, 71, 3, 66, 31, 0, 65, 52, 13]
Completa i programmi
Di seguito sono riportati i programmi completi per risolvere il problema degli zaini.
Python
from ortools.algorithms.python import knapsack_solver def main(): # Create the solver. solver = knapsack_solver.KnapsackSolver( knapsack_solver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "KnapsackExample", ) values = [ # fmt:off 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312 # fmt:on ] weights = [ # fmt: off [7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13], # fmt: on ] capacities = [850] solver.init(values, weights, capacities) computed_value = solver.solve() packed_items = [] packed_weights = [] total_weight = 0 print("Total value =", computed_value) for i in range(len(values)): if solver.best_solution_contains(i): packed_items.append(i) packed_weights.append(weights[0][i]) total_weight += weights[0][i] print("Total weight:", total_weight) print("Packed items:", packed_items) print("Packed_weights:", packed_weights) if __name__ == "__main__": main()
C++
#include <algorithm> #include <cstdint> #include <iterator> #include <numeric> #include <sstream> #include <vector> #include "ortools/algorithms/knapsack_solver.h" namespace operations_research { void RunKnapsackExample() { // Instantiate the solver. KnapsackSolver solver( KnapsackSolver::KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "KnapsackExample"); std::vector<int64_t> values = { 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312}; std::vector<std::vector<int64_t>> weights = { {7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13}}; std::vector<int64_t> capacities = {850}; solver.Init(values, weights, capacities); int64_t computed_value = solver.Solve(); // Print solution std::vector<int> packed_items; for (std::size_t i = 0; i < values.size(); ++i) { if (solver.BestSolutionContains(i)) packed_items.push_back(i); } std::ostringstream packed_items_ss; std::copy(packed_items.begin(), packed_items.end() - 1, std::ostream_iterator<int>(packed_items_ss, ", ")); packed_items_ss << packed_items.back(); std::vector<int64_t> packed_weights; packed_weights.reserve(packed_items.size()); for (const auto& it : packed_items) { packed_weights.push_back(weights[0][it]); } std::ostringstream packed_weights_ss; std::copy(packed_weights.begin(), packed_weights.end() - 1, std::ostream_iterator<int>(packed_weights_ss, ", ")); packed_weights_ss << packed_weights.back(); int64_t total_weights = std::accumulate(packed_weights.begin(), packed_weights.end(), int64_t{0}); LOG(INFO) << "Total value: " << computed_value; LOG(INFO) << "Packed items: {" << packed_items_ss.str() << "}"; LOG(INFO) << "Total weight: " << total_weights; LOG(INFO) << "Packed weights: {" << packed_weights_ss.str() << "}"; } } // namespace operations_research int main(int argc, char** argv) { operations_research::RunKnapsackExample(); return EXIT_SUCCESS; }
Java
package com.google.ortools.algorithms.samples; import com.google.ortools.Loader; import com.google.ortools.algorithms.KnapsackSolver; import java.util.ArrayList; /** * Sample showing how to model using the knapsack solver. */ public class Knapsack { private Knapsack() {} private static void solve() { KnapsackSolver solver = new KnapsackSolver( KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "test"); final long[] values = {360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312}; final long[][] weights = {{7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13}}; final long[] capacities = {850}; solver.init(values, weights, capacities); final long computedValue = solver.solve(); ArrayList<Integer> packedItems = new ArrayList<>(); ArrayList<Long> packedWeights = new ArrayList<>(); int totalWeight = 0; System.out.println("Total value = " + computedValue); for (int i = 0; i < values.length; i++) { if (solver.bestSolutionContains(i)) { packedItems.add(i); packedWeights.add(weights[0][i]); totalWeight = (int) (totalWeight + weights[0][i]); } } System.out.println("Total weight: " + totalWeight); System.out.println("Packed items: " + packedItems); System.out.println("Packed weights: " + packedWeights); } public static void main(String[] args) throws Exception { Loader.loadNativeLibraries(); Knapsack.solve(); } }
C#
using System; using Google.OrTools.Algorithms; public class Knapsack { static void Main() { KnapsackSolver solver = new KnapsackSolver( KnapsackSolver.SolverType.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "KnapsackExample"); long[] values = { 360, 83, 59, 130, 431, 67, 230, 52, 93, 125, 670, 892, 600, 38, 48, 147, 78, 256, 63, 17, 120, 164, 432, 35, 92, 110, 22, 42, 50, 323, 514, 28, 87, 73, 78, 15, 26, 78, 210, 36, 85, 189, 274, 43, 33, 10, 19, 389, 276, 312 }; long[,] weights = { { 7, 0, 30, 22, 80, 94, 11, 81, 70, 64, 59, 18, 0, 36, 3, 8, 15, 42, 9, 0, 42, 47, 52, 32, 26, 48, 55, 6, 29, 84, 2, 4, 18, 56, 7, 29, 93, 44, 71, 3, 86, 66, 31, 65, 0, 79, 20, 65, 52, 13 } }; long[] capacities = { 850 }; solver.Init(values, weights, capacities); long computedValue = solver.Solve(); Console.WriteLine("Optimal Value = " + computedValue); } }