Update MultipleKnapsack[Mip|Sat]
This commit is contained in:
committed by
Mizux Seiha
parent
628ea0465c
commit
1d48a794d4
@@ -12,28 +12,28 @@
|
||||
// limitations under the License.
|
||||
|
||||
// [START program]
|
||||
// Solve a multiple knapsack problem using a MIP solver.
|
||||
// [START import]
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.LinearSolver;
|
||||
// [END import]
|
||||
|
||||
public class MultipleKnapsackMip
|
||||
{
|
||||
// [START data_model]
|
||||
class DataModel
|
||||
{
|
||||
public static double[] Weights = { 48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36 };
|
||||
public static double[] Values = { 10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25 };
|
||||
public double[] BinCapacities = { 100, 100, 100, 100, 100 };
|
||||
public int NumItems = Weights.Length;
|
||||
public int NumBins = 5;
|
||||
}
|
||||
// [END data_model]
|
||||
|
||||
public static void Main()
|
||||
{
|
||||
// Instantiate the data problem.
|
||||
// [START data]
|
||||
DataModel data = new DataModel();
|
||||
double[] Weights = { 48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36 };
|
||||
double[] Values = { 10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25 };
|
||||
int NumItems = Weights.Length;
|
||||
int[] allItems = Enumerable.Range(0, NumItems).ToArray();
|
||||
|
||||
double[] BinCapacities = { 100, 100, 100, 100, 100 };
|
||||
int NumBins = BinCapacities.Length;
|
||||
int[] allBins = Enumerable.Range(0, NumBins).ToArray();
|
||||
// [END data]
|
||||
|
||||
// [START solver]
|
||||
@@ -41,49 +41,49 @@ public class MultipleKnapsackMip
|
||||
Solver solver = Solver.CreateSolver("SCIP");
|
||||
// [END solver]
|
||||
|
||||
// Variables
|
||||
// Variables.
|
||||
// [START variables]
|
||||
Variable[,] x = new Variable[data.NumItems, data.NumBins];
|
||||
for (int i = 0; i < data.NumItems; i++)
|
||||
Variable[,] x = new Variable[NumItems, NumBins];
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
for (int b = 0; b < data.NumBins; b++)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
x[i, b] = solver.MakeBoolVar($"x_{i}_{b}");
|
||||
}
|
||||
}
|
||||
// [END variables]
|
||||
|
||||
// Constraints
|
||||
// Constraints.
|
||||
// [START constraints]
|
||||
// Each item is assigned to at most one bin.
|
||||
for (int i = 0; i < data.NumItems; ++i)
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
Constraint constraint = solver.MakeConstraint(0, 1, "");
|
||||
for (int b = 0; b < data.NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
constraint.SetCoefficient(x[i, b], 1);
|
||||
}
|
||||
}
|
||||
|
||||
// The amount packed in each bin cannot exceed its capacity.
|
||||
for (int b = 0; b < data.NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
Constraint constraint = solver.MakeConstraint(0, data.BinCapacities[b], "");
|
||||
for (int i = 0; i < data.NumItems; ++i)
|
||||
Constraint constraint = solver.MakeConstraint(0, BinCapacities[b], "");
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
constraint.SetCoefficient(x[i, b], DataModel.Weights[i]);
|
||||
constraint.SetCoefficient(x[i, b], Weights[i]);
|
||||
}
|
||||
}
|
||||
// [END constraints]
|
||||
|
||||
// Objective
|
||||
// Objective.
|
||||
// [START objective]
|
||||
Objective objective = solver.Objective();
|
||||
for (int i = 0; i < data.NumItems; ++i)
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
for (int b = 0; b < data.NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
objective.SetCoefficient(x[i, b], DataModel.Values[i]);
|
||||
objective.SetCoefficient(x[i, b], Values[i]);
|
||||
}
|
||||
}
|
||||
objective.SetMaximization();
|
||||
@@ -99,18 +99,18 @@ public class MultipleKnapsackMip
|
||||
{
|
||||
Console.WriteLine($"Total packed value: {solver.Objective().Value()}");
|
||||
double TotalWeight = 0.0;
|
||||
for (int b = 0; b < data.NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
double BinWeight = 0.0;
|
||||
double BinValue = 0.0;
|
||||
Console.WriteLine("Bin " + b);
|
||||
for (int i = 0; i < data.NumItems; ++i)
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
if (x[i, b].SolutionValue() == 1)
|
||||
{
|
||||
Console.WriteLine($"Item {i} weight: {DataModel.Weights[i]} values: {DataModel.Values[i]}");
|
||||
BinWeight += DataModel.Weights[i];
|
||||
BinValue += DataModel.Values[i];
|
||||
Console.WriteLine($"Item {i} weight: {Weights[i]} values: {Values[i]}");
|
||||
BinWeight += Weights[i];
|
||||
BinValue += Values[i];
|
||||
}
|
||||
}
|
||||
Console.WriteLine("Packed bin weight: " + BinWeight);
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// [START program]
|
||||
// MIP example that solves a multiple knapsack problem.
|
||||
// Solve a multiple knapsack problem using a MIP solver.
|
||||
package com.google.ortools.linearsolver.samples;
|
||||
// [START import]
|
||||
import com.google.ortools.Loader;
|
||||
@@ -20,24 +20,23 @@ import com.google.ortools.linearsolver.MPConstraint;
|
||||
import com.google.ortools.linearsolver.MPObjective;
|
||||
import com.google.ortools.linearsolver.MPSolver;
|
||||
import com.google.ortools.linearsolver.MPVariable;
|
||||
import java.util.stream.IntStream;
|
||||
// [END import]
|
||||
|
||||
/** Multiple knapsack problem. */
|
||||
public class MultipleKnapsackMip {
|
||||
// [START data_model]
|
||||
static class DataModel {
|
||||
public final double[] weights = {48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36};
|
||||
public final double[] values = {10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25};
|
||||
public final int numItems = weights.length;
|
||||
public final int numBins = 5;
|
||||
public final double[] binCapacities = {100, 100, 100, 100, 100};
|
||||
}
|
||||
// [END data_model]
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
public static void main(String[] args) {
|
||||
Loader.loadNativeLibraries();
|
||||
// Instantiate the data problem.
|
||||
// [START data]
|
||||
final DataModel data = new DataModel();
|
||||
final double[] weights = {48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36};
|
||||
final double[] values = {10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25};
|
||||
final int numItems = weights.length;
|
||||
final int[] allItems = IntStream.range(0, numItems).toArray();
|
||||
|
||||
final double[] binCapacities = {100, 100, 100, 100, 100};
|
||||
final int numBins = binCapacities.length;
|
||||
final int[] allBins = IntStream.range(0, numBins).toArray();
|
||||
// [END data]
|
||||
|
||||
// [START solver]
|
||||
@@ -51,9 +50,9 @@ public class MultipleKnapsackMip {
|
||||
|
||||
// Variables.
|
||||
// [START variables]
|
||||
MPVariable[][] x = new MPVariable[data.numItems][data.numBins];
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
MPVariable[][] x = new MPVariable[numItems][numBins];
|
||||
for (int i : allItems) {
|
||||
for (int b : allBins) {
|
||||
x[i][b] = solver.makeBoolVar("x_" + i + "_" + b);
|
||||
}
|
||||
}
|
||||
@@ -62,52 +61,52 @@ public class MultipleKnapsackMip {
|
||||
// Constraints.
|
||||
// [START constraints]
|
||||
// Each item is assigned to at most one bin.
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
for (int i : allItems) {
|
||||
MPConstraint constraint = solver.makeConstraint(0, 1, "");
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
for (int b : allBins) {
|
||||
constraint.setCoefficient(x[i][b], 1);
|
||||
}
|
||||
}
|
||||
|
||||
// The amount packed in each bin cannot exceed its capacity.
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
MPConstraint constraint = solver.makeConstraint(0, data.binCapacities[b], "");
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
constraint.setCoefficient(x[i][b], data.weights[i]);
|
||||
for (int b : allBins) {
|
||||
MPConstraint constraint = solver.makeConstraint(0, binCapacities[b], "");
|
||||
for (int i : allItems) {
|
||||
constraint.setCoefficient(x[i][b], weights[i]);
|
||||
}
|
||||
}
|
||||
// [END constraints]
|
||||
|
||||
// Objective.
|
||||
// [START objective]
|
||||
// Maximize total value of packed items.
|
||||
MPObjective objective = solver.objective();
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
objective.setCoefficient(x[i][b], data.values[i]);
|
||||
for (int i : allItems) {
|
||||
for (int b : allBins) {
|
||||
objective.setCoefficient(x[i][b], values[i]);
|
||||
}
|
||||
}
|
||||
objective.setMaximization();
|
||||
// [END objective]
|
||||
|
||||
// [START solve]
|
||||
final MPSolver.ResultStatus resultStatus = solver.solve();
|
||||
final MPSolver.ResultStatus status = solver.solve();
|
||||
// [END solve]
|
||||
|
||||
// [START print_solution]
|
||||
// Check that the problem has an optimal solution.
|
||||
if (resultStatus == MPSolver.ResultStatus.OPTIMAL) {
|
||||
if (status == MPSolver.ResultStatus.OPTIMAL) {
|
||||
System.out.println("Total packed value: " + objective.value());
|
||||
double totalWeight = 0;
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
for (int b : allBins) {
|
||||
double binWeight = 0;
|
||||
double binValue = 0;
|
||||
System.out.println("Bin " + b);
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
for (int i : allItems) {
|
||||
if (x[i][b].solutionValue() == 1) {
|
||||
System.out.println(
|
||||
"Item " + i + " weight: " + data.weights[i] + " value: " + data.values[i]);
|
||||
binWeight += data.weights[i];
|
||||
binValue += data.values[i];
|
||||
System.out.println("Item " + i + " weight: " + weights[i] + " value: " + values[i]);
|
||||
binWeight += weights[i];
|
||||
binValue += values[i];
|
||||
}
|
||||
}
|
||||
System.out.println("Packed bin weight: " + binWeight);
|
||||
|
||||
@@ -57,8 +57,7 @@ void MultipleKnapsackMip() {
|
||||
num_items, std::vector<const MPVariable*>(num_bins));
|
||||
for (int i : all_items) {
|
||||
for (int b : all_bins) {
|
||||
x[i][b] = solver->MakeBoolVar(
|
||||
absl::StrFormat("x_%d_%d", i, b));
|
||||
x[i][b] = solver->MakeBoolVar(absl::StrFormat("x_%d_%d", i, b));
|
||||
}
|
||||
}
|
||||
// [END variables]
|
||||
@@ -73,7 +72,6 @@ void MultipleKnapsackMip() {
|
||||
}
|
||||
solver->MakeRowConstraint(sum <= 1.0);
|
||||
}
|
||||
|
||||
// The amount packed in each bin cannot exceed its capacity.
|
||||
for (int b : all_bins) {
|
||||
LinearExpr bin_weight;
|
||||
@@ -111,9 +109,8 @@ void MultipleKnapsackMip() {
|
||||
double bin_value = 0.0;
|
||||
for (int i : all_items) {
|
||||
if (x[i][b]->solution_value() > 0) {
|
||||
LOG(INFO) << "Item " << i
|
||||
<< " weight: " << weights[i]
|
||||
<< " value: " << values[i];
|
||||
LOG(INFO) << "Item " << i << " weight: " << weights[i]
|
||||
<< " value: " << values[i];
|
||||
bin_weight += weights[i];
|
||||
bin_value += values[i];
|
||||
}
|
||||
|
||||
@@ -18,31 +18,28 @@ from ortools.linear_solver import pywraplp
|
||||
# [END import]
|
||||
|
||||
|
||||
# [START data_model]
|
||||
def create_data_model():
|
||||
"""Create the data for the example."""
|
||||
def main():
|
||||
# [START data]
|
||||
data = {}
|
||||
data['weights'] = [48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36]
|
||||
data['values'] = [10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25]
|
||||
data['weights'] = [
|
||||
48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36
|
||||
]
|
||||
data['values'] = [
|
||||
10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25
|
||||
]
|
||||
assert len(data['weights']) == len(data['values'])
|
||||
data['num_items'] = len(data['weights'])
|
||||
data['all_items'] = range(data['num_items'])
|
||||
|
||||
data['bin_capacities'] = [100, 100, 100, 100, 100]
|
||||
data['num_bins'] = len(data['bin_capacities'])
|
||||
data['all_bins'] = range(data['num_bins'])
|
||||
return data
|
||||
# [END data_model]
|
||||
|
||||
|
||||
def main():
|
||||
# [START data]
|
||||
data = create_data_model()
|
||||
# [END data]
|
||||
|
||||
# Create the mip solver with the SCIP backend.
|
||||
# [START solver]
|
||||
solver = pywraplp.Solver.CreateSolver('SCIP')
|
||||
if solver == None:
|
||||
if solver is None:
|
||||
print('SCIP solver unavailable.')
|
||||
return
|
||||
# [END solver]
|
||||
@@ -93,7 +90,9 @@ def main():
|
||||
bin_value = 0
|
||||
for i in data['all_items']:
|
||||
if x[i, b].solution_value() > 0:
|
||||
print(f"Item {i} weight: {data['weights'][i]} value: {data['values'][i]}")
|
||||
print(
|
||||
f"Item {i} weight: {data['weights'][i]} value: {data['values'][i]}"
|
||||
)
|
||||
bin_weight += data['weights'][i]
|
||||
bin_value += data['values'][i]
|
||||
print(f'Packed bin weight: {bin_weight}')
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// [START program]
|
||||
// Solves a multiple knapsack problem using the CP-SAT solver.
|
||||
// [START import]
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
@@ -23,12 +24,14 @@ public class MultipleKnapsackSat
|
||||
{
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
// Instantiate the data problem.
|
||||
// [START data]
|
||||
long[] Weights = { 48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36 };
|
||||
long[] Values = { 10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25 };
|
||||
int[] Weights = { 48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36 };
|
||||
int[] Values = { 10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25 };
|
||||
int NumItems = Weights.Length;
|
||||
int[] allItems = Enumerable.Range(0, NumItems).ToArray();
|
||||
long[] BinCapacities = { 100, 100, 100, 100, 100 };
|
||||
|
||||
int[] BinCapacities = { 100, 100, 100, 100, 100 };
|
||||
int NumBins = BinCapacities.Length;
|
||||
int[] allBins = Enumerable.Range(0, NumBins).ToArray();
|
||||
// [END data]
|
||||
@@ -38,25 +41,25 @@ public class MultipleKnapsackSat
|
||||
CpModel model = new CpModel();
|
||||
// [END model]
|
||||
|
||||
// Variables
|
||||
// Variables.
|
||||
// [START variables]
|
||||
IntVar[,] x = new IntVar[NumItems, NumBins];
|
||||
for (int i = 0; i < NumItems; ++i)
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
for (int j = 0; j < NumBins; ++j)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
x[i, j] = model.NewBoolVar($"x_{i}_{j}");
|
||||
x[i, b] = model.NewBoolVar($"x_{i}_{b}");
|
||||
}
|
||||
}
|
||||
// [END variables]
|
||||
|
||||
// Constraints
|
||||
// Constraints.
|
||||
// [START constraints]
|
||||
// Each item is assigned to at most one bin.
|
||||
for (int i = 0; i < NumItems; ++i)
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
IntVar[] vars = new IntVar[NumBins];
|
||||
for (int b = 0; b < NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
vars[b] = x[i, b];
|
||||
}
|
||||
@@ -64,36 +67,35 @@ public class MultipleKnapsackSat
|
||||
}
|
||||
|
||||
// The amount packed in each bin cannot exceed its capacity.
|
||||
for (int b = 0; b < NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
LinearExpr[] exprs = new LinearExpr[NumItems];
|
||||
for (int i = 0; i < NumItems; ++i)
|
||||
LinearExpr[] binWeights = new LinearExpr[NumItems];
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
exprs[i] = LinearExpr.Affine(x[i, b], /*coeff=*/Weights[i], /*offset=*/0);
|
||||
binWeights[i] = LinearExpr.Term(x[i, b], /*coeff=*/Weights[i]);
|
||||
}
|
||||
model.Add(LinearExpr.Sum(exprs) <= 1);
|
||||
model.Add(LinearExpr.Sum(binWeights) <= 1);
|
||||
}
|
||||
// [END constraints]
|
||||
|
||||
// Objective
|
||||
// Objective.
|
||||
// [START objective]
|
||||
LinearExpr[] obj = new LinearExpr[NumItems * NumBins];
|
||||
for (int i = 0; i < NumItems; ++i)
|
||||
LinearExpr[] objective = new LinearExpr[NumItems * NumBins];
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
for (int b = 0; b < NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
int k = i * NumBins + b;
|
||||
obj[i] = LinearExpr.Affine(x[i, b], /*coeff=*/Values[i], /*offset=*/0);
|
||||
objective[k] = LinearExpr.Term(x[i, b], /*coeff=*/Values[i]);
|
||||
}
|
||||
}
|
||||
model.Maximize(LinearExpr.Sum(obj));
|
||||
model.Maximize(LinearExpr.Sum(objective));
|
||||
// [END objective]
|
||||
|
||||
// Solve
|
||||
// [START solve]
|
||||
CpSolver solver = new CpSolver();
|
||||
CpSolverStatus status = solver.Solve(model);
|
||||
Console.WriteLine($"Solve status: {status}");
|
||||
// [END solve]
|
||||
|
||||
// Print solution.
|
||||
@@ -103,12 +105,12 @@ public class MultipleKnapsackSat
|
||||
{
|
||||
Console.WriteLine($"Total packed value: {solver.ObjectiveValue}");
|
||||
double TotalWeight = 0.0;
|
||||
for (int b = 0; b < NumBins; ++b)
|
||||
foreach (int b in allBins)
|
||||
{
|
||||
double BinWeight = 0.0;
|
||||
double BinValue = 0.0;
|
||||
Console.WriteLine($"Bin {b}");
|
||||
for (int i = 0; i < NumItems; ++i)
|
||||
foreach (int i in allItems)
|
||||
{
|
||||
if (solver.Value(x[i, b]) == 1)
|
||||
{
|
||||
@@ -137,5 +139,4 @@ public class MultipleKnapsackSat
|
||||
// [END statistics]
|
||||
}
|
||||
}
|
||||
|
||||
// [END program]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// [START program]
|
||||
// Solves a multiple knapsack problem using the CP-SAT solver.
|
||||
package com.google.ortools.sat.samples;
|
||||
// [START import]
|
||||
import com.google.ortools.Loader;
|
||||
@@ -20,118 +21,105 @@ import com.google.ortools.sat.CpSolver;
|
||||
import com.google.ortools.sat.CpSolverStatus;
|
||||
import com.google.ortools.sat.IntVar;
|
||||
import com.google.ortools.sat.LinearExpr;
|
||||
import java.util.stream.IntStream;
|
||||
// [END import]
|
||||
|
||||
/** Sample showing how to solve a multiple knapsack problem. */
|
||||
public class MultipleKnapsackSat {
|
||||
// [START data]
|
||||
static class DataModel {
|
||||
int[] items = new int[] {48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36};
|
||||
int[] values = new int[] {10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25};
|
||||
int[] binCapacities = new int[] {100, 100, 100, 100, 100};
|
||||
int numItems = items.length;
|
||||
int numBins = 5;
|
||||
}
|
||||
// [END data]
|
||||
|
||||
// [START solution_printer]
|
||||
static void printSolution(
|
||||
DataModel data, CpSolver solver, IntVar[][] x, IntVar[] load, IntVar[] value) {
|
||||
System.out.printf("Optimal objective value: %f%n", solver.objectiveValue());
|
||||
System.out.println();
|
||||
long packedWeight = 0;
|
||||
long packedValue = 0;
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
System.out.println("Bin " + b);
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
if (solver.value(x[i][b]) > 0) {
|
||||
System.out.println(
|
||||
"Item " + i + " - Weight: " + data.items[i] + " Value: " + data.values[i]);
|
||||
}
|
||||
}
|
||||
System.out.println("Packed bin weight: " + solver.value(load[b]));
|
||||
packedWeight = packedWeight + solver.value(load[b]);
|
||||
System.out.println("Packed bin value: " + solver.value(value[b]) + "\n");
|
||||
packedValue = packedValue + solver.value(value[b]);
|
||||
}
|
||||
System.out.println("Total packed weight: " + packedWeight);
|
||||
System.out.println("Total packed value: " + packedValue);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Loader.loadNativeLibraries();
|
||||
// Instantiate the data problem.
|
||||
// [START data]
|
||||
final DataModel data = new DataModel();
|
||||
final int[] weights = {48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36};
|
||||
final int[] values = {10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25};
|
||||
final int numItems = weights.length;
|
||||
final int[] allItems = IntStream.range(0, numItems).toArray();
|
||||
|
||||
final int[] binCapacities = {100, 100, 100, 100, 100};
|
||||
final int numBins = binCapacities.length;
|
||||
final int[] allBins = IntStream.range(0, numBins).toArray();
|
||||
// [END data]
|
||||
int totalValue = 0;
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
totalValue = totalValue + data.values[i];
|
||||
}
|
||||
|
||||
// [START model]
|
||||
CpModel model = new CpModel();
|
||||
// [END model]
|
||||
|
||||
// Variables.
|
||||
// [START variables]
|
||||
IntVar[][] x = new IntVar[data.numItems][data.numBins];
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
x[i][b] = model.newIntVar(0, 1, "x_" + i + "_" + b);
|
||||
IntVar[][] x = new IntVar[numItems][numBins];
|
||||
for (int i : allItems) {
|
||||
for (int b : allBins) {
|
||||
x[i][b] = model.newBoolVar("x_" + i + "_" + b);
|
||||
}
|
||||
}
|
||||
// Main variables.
|
||||
// Load and value variables.
|
||||
IntVar[] load = new IntVar[data.numBins];
|
||||
IntVar[] value = new IntVar[data.numBins];
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
load[b] = model.newIntVar(0, data.binCapacities[b], "load_" + b);
|
||||
value[b] = model.newIntVar(0, totalValue, "value_" + b);
|
||||
}
|
||||
|
||||
// Links load and value with x.
|
||||
int[] sizes = new int[data.numItems];
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
sizes[i] = data.items[i];
|
||||
}
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
IntVar[] vars = new IntVar[data.numItems];
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
vars[i] = x[i][b];
|
||||
}
|
||||
model.addEquality(LinearExpr.scalProd(vars, data.items), load[b]);
|
||||
model.addEquality(LinearExpr.scalProd(vars, data.values), value[b]);
|
||||
}
|
||||
// [END variables]
|
||||
|
||||
// Constraints.
|
||||
// [START constraints]
|
||||
// Each item can be in at most one bin.
|
||||
// Place all items.
|
||||
for (int i = 0; i < data.numItems; ++i) {
|
||||
IntVar[] vars = new IntVar[data.numBins];
|
||||
for (int b = 0; b < data.numBins; ++b) {
|
||||
// Each item is assigned to at most one bin.
|
||||
for (int i : allItems) {
|
||||
IntVar[] vars = new IntVar[numBins];
|
||||
for (int b : allBins) {
|
||||
vars[b] = x[i][b];
|
||||
}
|
||||
model.addLessOrEqual(LinearExpr.sum(vars), 1);
|
||||
}
|
||||
|
||||
// The amount packed in each bin cannot exceed its capacity.
|
||||
for (int b : allBins) {
|
||||
IntVar[] binWeights = new IntVar[numItems];
|
||||
for (int i : allItems) {
|
||||
binWeights[i] = LinearExpr.term(x[i][b], weights[i]);
|
||||
}
|
||||
model.addLessOrEqual(LinearExpr.sum(binWeights), 1);
|
||||
}
|
||||
// [END constraints]
|
||||
// Maximize sum of load.
|
||||
|
||||
// Objective.
|
||||
// [START objective]
|
||||
model.maximize(LinearExpr.sum(value));
|
||||
// Maximize total value of packed items.
|
||||
IntVar[] objective = new IntVar[numItems * numBins];
|
||||
for (int i : allItems) {
|
||||
for (int b : allBins) {
|
||||
int k = i * numBins + b;
|
||||
objective[k] = LinearExpr.term(x[i][b], values[i]);
|
||||
}
|
||||
}
|
||||
model.maximize(LinearExpr.sum(objective));
|
||||
// [END objective]
|
||||
|
||||
// [START solve]
|
||||
CpSolver solver = new CpSolver();
|
||||
CpSolverStatus status = solver.solve(model);
|
||||
final CpSolverStatus status = solver.solve(model);
|
||||
// [END solve]
|
||||
|
||||
// [START print_solution]
|
||||
System.out.println("Solve status: " + status);
|
||||
// Check that the problem has an optimal solution.
|
||||
if (status == CpSolverStatus.OPTIMAL) {
|
||||
printSolution(data, solver, x, load, value);
|
||||
System.out.println("Total packed value: " + solver.objectiveValue());
|
||||
long totalWeight = 0;
|
||||
for (int b : allBins) {
|
||||
long binWeight = 0;
|
||||
long binValue = 0;
|
||||
System.out.println("Bin " + b);
|
||||
for (int i : allItems) {
|
||||
if (solver.value(x[i][b]) > 0) {
|
||||
System.out.println("Item " + i + " weight: " + weights[i] + " value: " + values[i]);
|
||||
binWeight += weights[i];
|
||||
binValue += values[i];
|
||||
}
|
||||
}
|
||||
System.out.println("Packed bin weight: " + binWeight);
|
||||
System.out.println("Packed bin value: " + binValue);
|
||||
totalWeight += binWeight;
|
||||
}
|
||||
System.out.println("Total packed weight: " + totalWeight);
|
||||
} else {
|
||||
System.err.println("The problem does not have an optimal solution.");
|
||||
}
|
||||
// [END print_solution]
|
||||
}
|
||||
|
||||
private MultipleKnapsackSat() {}
|
||||
}
|
||||
// [END program]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
// [START program]
|
||||
// Solves a multiple knapsack problem using the CP-SAT solver.
|
||||
// [START import]
|
||||
#include <map>
|
||||
#include <numeric>
|
||||
@@ -31,13 +32,12 @@ void MultipleKnapsackSat() {
|
||||
{48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36}};
|
||||
const std::vector<int> values = {
|
||||
{10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25}};
|
||||
const int total_value = std::accumulate(values.begin(), values.end(), 0);
|
||||
const int num_items = weights.size();
|
||||
const int num_items = static_cast<int>(weights.size());
|
||||
std::vector<int> all_items(num_items);
|
||||
std::iota(all_items.begin(), all_items.end(), 0);
|
||||
|
||||
const std::vector<int> bin_capacities = {{100, 100, 100, 100, 100}};
|
||||
const int num_bins = bin_capacities.size();
|
||||
const int num_bins = static_cast<int>(bin_capacities.size());
|
||||
std::vector<int> all_bins(num_bins);
|
||||
std::iota(all_bins.begin(), all_bins.end(), 0);
|
||||
// [END data]
|
||||
@@ -53,18 +53,9 @@ void MultipleKnapsackSat() {
|
||||
for (int i : all_items) {
|
||||
for (int b : all_bins) {
|
||||
auto key = std::make_tuple(i, b);
|
||||
x[key] = cp_model.NewBoolVar().WithName(
|
||||
absl::StrFormat("x_%d_%d", i, b));
|
||||
x[key] = cp_model.NewBoolVar().WithName(absl::StrFormat("x_%d_%d", i, b));
|
||||
}
|
||||
}
|
||||
|
||||
// Load variables.
|
||||
std::vector<IntVar> load(num_bins);
|
||||
std::vector<IntVar> value(num_bins);
|
||||
for (int b : all_bins) {
|
||||
load[b] = cp_model.NewIntVar({0, bin_capacities[b]});
|
||||
value[b] = cp_model.NewIntVar({0, total_value});
|
||||
}
|
||||
// [END variables]
|
||||
|
||||
// Constraints.
|
||||
@@ -119,15 +110,14 @@ void MultipleKnapsackSat() {
|
||||
for (int i : all_items) {
|
||||
auto key = std::make_tuple(i, b);
|
||||
if (SolutionIntegerValue(response, x[key]) > 0) {
|
||||
LOG(INFO) << "Item " << i
|
||||
<< " weight: " << weights[i]
|
||||
<< " value: " << values[i];
|
||||
LOG(INFO) << "Item " << i << " weight: " << weights[i]
|
||||
<< " value: " << values[i];
|
||||
bin_weight += weights[i];
|
||||
bin_value += values[i];
|
||||
}
|
||||
}
|
||||
LOG(INFO) << "Packed bin weight: " << bin_weight;
|
||||
LOG(INFO) << "Packed bin value: " << bin_value;
|
||||
LOG(INFO) << "Packed bin value: " << bin_value;
|
||||
total_weight += bin_weight;
|
||||
}
|
||||
LOG(INFO) << "Total packed weight: " << total_weight;
|
||||
|
||||
@@ -18,25 +18,22 @@ from ortools.sat.python import cp_model
|
||||
# [END import]
|
||||
|
||||
|
||||
# [START data_model]
|
||||
def create_data_model():
|
||||
"""Create the data for the example."""
|
||||
def main():
|
||||
# [START data]
|
||||
data = {}
|
||||
data['weights'] = [48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36]
|
||||
data['values'] = [10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25]
|
||||
data['weights'] = [
|
||||
48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36
|
||||
]
|
||||
data['values'] = [
|
||||
10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25
|
||||
]
|
||||
assert len(data['weights']) == len(data['values'])
|
||||
data['num_items'] = len(data['weights'])
|
||||
data['all_items'] = range(data['num_items'])
|
||||
|
||||
data['bin_capacities'] = [100, 100, 100, 100, 100]
|
||||
data['num_bins'] = len(data['bin_capacities'])
|
||||
data['all_bins'] = range(data['num_bins'])
|
||||
return data
|
||||
# [END data_model]
|
||||
|
||||
|
||||
def main():
|
||||
# [START data]
|
||||
data = create_data_model()
|
||||
# [END data]
|
||||
|
||||
# [START model]
|
||||
@@ -71,7 +68,8 @@ def main():
|
||||
objective = []
|
||||
for i in data['all_items']:
|
||||
for b in data['all_bins']:
|
||||
objective.append(cp_model.LinearExpr.Term(x[i, b], data['values'][i]))
|
||||
objective.append(
|
||||
cp_model.LinearExpr.Term(x[i, b], data['values'][i]))
|
||||
model.Maximize(cp_model.LinearExpr.Sum(objective))
|
||||
# [END objective]
|
||||
|
||||
@@ -90,7 +88,9 @@ def main():
|
||||
bin_value = 0
|
||||
for i in data['all_items']:
|
||||
if solver.Value(x[i, b]) > 0:
|
||||
print(f"Item {i} weight: {data['weights'][i]} value: {data['values'][i]}")
|
||||
print(
|
||||
f"Item {i} weight: {data['weights'][i]} value: {data['values'][i]}"
|
||||
)
|
||||
bin_weight += data['weights'][i]
|
||||
bin_value += data['values'][i]
|
||||
print(f'Packed bin weight: {bin_weight}')
|
||||
|
||||
Reference in New Issue
Block a user