Add AssignmentMIP samples
This commit is contained in:
committed by
Mizux Seiha
parent
b58a4607b4
commit
bcc6bd70a1
@@ -334,6 +334,7 @@ test_cc_graph_samples: \
|
||||
|
||||
.PHONY: test_cc_linear_solver_samples # Build and Run all C++ LP Samples (located in ortools/linear_solver/samples)
|
||||
test_cc_linear_solver_samples: \
|
||||
rcc_assignment_mip \
|
||||
rcc_bin_packing_mip \
|
||||
rcc_integer_programming_example \
|
||||
rcc_linear_programming_example \
|
||||
|
||||
@@ -520,6 +520,7 @@ test_dotnet_graph_samples: ;
|
||||
|
||||
.PHONY: test_dotnet_linear_solver_samples # Build and Run all .Net LP Samples (located in ortools/linear_solver/samples)
|
||||
test_dotnet_linear_solver_samples:
|
||||
$(MAKE) run SOURCE=ortools/linear_solver/samples/AssignmentMip.cs
|
||||
$(MAKE) run SOURCE=ortools/linear_solver/samples/BinPackingMip.cs
|
||||
$(MAKE) run SOURCE=ortools/linear_solver/samples/LinearProgrammingExample.cs
|
||||
$(MAKE) run SOURCE=ortools/linear_solver/samples/MipVarArray.cs
|
||||
|
||||
@@ -461,6 +461,7 @@ test_java_graph_samples: \
|
||||
|
||||
.PHONY: test_java_linear_solver_samples # Build and Run all Java LP Samples (located in ortools/linear_solver/samples)
|
||||
test_java_linear_solver_samples: \
|
||||
rjava_AssignmentMip \
|
||||
rjava_BinPackingMip \
|
||||
rjava_LinearProgrammingExample \
|
||||
rjava_MipVarArray \
|
||||
|
||||
@@ -591,6 +591,7 @@ test_python_graph_samples: \
|
||||
|
||||
.PHONY: test_python_linear_solver_samples # Run all Python LP Samples (located in ortools/linear_solver/samples)
|
||||
test_python_linear_solver_samples: \
|
||||
rpy_assignment_mip \
|
||||
rpy_bin_packing_mip \
|
||||
rpy_integer_programming_example \
|
||||
rpy_linear_programming_example \
|
||||
|
||||
116
ortools/linear_solver/samples/AssignmentMip.cs
Normal file
116
ortools/linear_solver/samples/AssignmentMip.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2010-2018 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
using System;
|
||||
using Google.OrTools.LinearSolver;
|
||||
|
||||
public class AssignmentMip
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
// Data.
|
||||
// [START data_model]
|
||||
int[,] costs = {
|
||||
{90, 80, 75, 70},
|
||||
{35, 85, 55, 65},
|
||||
{125, 95, 90, 95},
|
||||
{45, 110, 95, 115},
|
||||
{50, 100, 90, 100},
|
||||
};
|
||||
int numWorkers = costs.GetLength(0);
|
||||
int numTasks = costs.GetLength(1);
|
||||
// [END data_model]
|
||||
|
||||
// Model.
|
||||
// [START model]
|
||||
Solver solver = Solver.CreateSolver("AssignmentMip", "CBC_MIXED_INTEGER_PROGRAMMING");
|
||||
// [END model]
|
||||
|
||||
// Variables.
|
||||
// [START variables]
|
||||
// x[i, j] is an array of 0-1 variables, which will be 1
|
||||
// if worker i is assigned to task j.
|
||||
Variable[,] x = new Variable[data.NumItems, data.NumBins];
|
||||
for (int i = 0; i < numWorkers; ++i)
|
||||
{
|
||||
for (int j = 0; j < numTasks; ++j)
|
||||
{
|
||||
x[i, j] = solver.MakeIntVar(0, 1, $"worker_{i}_task_{j}");
|
||||
}
|
||||
}
|
||||
// [END variables]
|
||||
|
||||
// Constraints
|
||||
// [START constraints]
|
||||
// Each worker is assigned to at most one task.
|
||||
for (int i = 0; i < numWorkers; ++i)
|
||||
{
|
||||
Constraint constraint = solver.MakeConstraint(0, 1, "");
|
||||
for (int j = 0; j < numTasks; ++j)
|
||||
{
|
||||
constraint.SetCoefficient(x[i, j], 1);
|
||||
}
|
||||
}
|
||||
// Each task is assigned to exactly one worker.
|
||||
for (int j = 0; j < numTasks; ++j)
|
||||
{
|
||||
Constraint constraint = solver.MakeConstraint(1, 1, "");
|
||||
for (int i = 0; i < numWorkers; ++i)
|
||||
{
|
||||
constraint.SetCoefficient(x[i, j], 1);
|
||||
}
|
||||
}
|
||||
// [END constraints]
|
||||
|
||||
// Objective
|
||||
// [START objective]
|
||||
Objective objective = solver.Objective();
|
||||
for (int i = 0; i < numWorkers; ++i)
|
||||
{
|
||||
for (int j = 0; j < numTasks; ++j)
|
||||
{
|
||||
objective.SetCoefficient(x[i, j], 1);
|
||||
}
|
||||
}
|
||||
objective.SetMinimization();
|
||||
// [END objective]
|
||||
|
||||
// Solve
|
||||
// [START solve]
|
||||
Solver.ResultStatus resultStatus = solver.Solve();
|
||||
// [END solve]
|
||||
|
||||
// Print solution.
|
||||
// [START print_solution]
|
||||
// Check that the problem has a feasible solution.
|
||||
if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
|
||||
{
|
||||
Console.WriteLine($"Total cost: {solver.ObjectiveValue}\n");
|
||||
for (int i = 0; i < numWorkers; ++i)
|
||||
{
|
||||
for (int j = 0; j < numTasks; ++j)
|
||||
{
|
||||
// Test if x[i, j] is 0 or 1 (with tolerance for floating point
|
||||
// arithmetic).
|
||||
if (x[i, j].SolutionValue() > 0.5)
|
||||
{
|
||||
Console.WriteLine($"Worker {i} assigned to task {j}. Cost: {costs[i, j]}");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Console.WriteLine("No solution found.");
|
||||
}
|
||||
// [END print_solution]
|
||||
}
|
||||
}
|
||||
24
ortools/linear_solver/samples/AssignmentMip.csproj
Normal file
24
ortools/linear_solver/samples/AssignmentMip.csproj
Normal file
@@ -0,0 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||
<EnableDefaultItems>false</EnableDefaultItems>
|
||||
<!-- see https://github.com/dotnet/docs/issues/12237 -->
|
||||
<RollForward>LatestMajor</RollForward>
|
||||
<RestoreSources>../../../packages;$(RestoreSources);https://api.nuget.org/v3/index.json</RestoreSources>
|
||||
<AssemblyName>Google.OrTools.AssignmentMip</AssemblyName>
|
||||
<IsPackable>true</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="AssignmentMip.cs" />
|
||||
<PackageReference Include="Google.OrTools" Version="7.7.*" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
120
ortools/linear_solver/samples/AssignmentMip.java
Normal file
120
ortools/linear_solver/samples/AssignmentMip.java
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright 2010-2018 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// [START program]
|
||||
package com.google.ortools.linearsolver.samples;
|
||||
// [START import]
|
||||
import com.google.ortools.linearsolver.MPConstraint;
|
||||
import com.google.ortools.linearsolver.MPObjective;
|
||||
import com.google.ortools.linearsolver.MPSolver;
|
||||
import com.google.ortools.linearsolver.MPVariable;
|
||||
// [END import]
|
||||
|
||||
/** MIP example that solves an assignment problem. */
|
||||
public class AssignmentMip {
|
||||
static {
|
||||
System.loadLibrary("jniortools");
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Data
|
||||
// [START data_model]
|
||||
double[][] costs = {
|
||||
{90, 80, 75, 70},
|
||||
{35, 85, 55, 65},
|
||||
{125, 95, 90, 95},
|
||||
{45, 110, 95, 115},
|
||||
{50, 100, 90, 100},
|
||||
};
|
||||
int numWorkers = costs.length;
|
||||
int numTasks = costs[0].length;
|
||||
// [END data_model]
|
||||
|
||||
// Solver
|
||||
// [START solver]
|
||||
// Create the linear solver with the CBC backend.
|
||||
MPSolver solver = new MPSolver(
|
||||
"AssignmentMip", MPSolver.OptimizationProblemType.CBC_MIXED_INTEGER_PROGRAMMING);
|
||||
// [END solver]
|
||||
|
||||
// Variables
|
||||
// [START variables]
|
||||
// x[i][j] is an array of 0-1 variables, which will be 1
|
||||
// if worker i is assigned to task j.
|
||||
MPVariable[][] x = new MPVariable[numWorkers][numTasks];
|
||||
for (int i = 0; i < numWorkers; ++i) {
|
||||
for (int j = 0; j < numTasks; ++j) {
|
||||
x[i][j] = solver.makeIntVar(0, 1, "");
|
||||
}
|
||||
}
|
||||
// [END variables]
|
||||
|
||||
// Constraints
|
||||
// [START constraints]
|
||||
// Each worker is assigned to at most one task.
|
||||
for (int i = 0; i < numWorkers; ++i) {
|
||||
MPConstraint constraint = solver.makeConstraint(0, 1, "");
|
||||
for (int j = 0; j < numTasks; ++j) {
|
||||
constraint.setCoefficient(x[i][j], 1);
|
||||
}
|
||||
}
|
||||
// Each task is assigned to exactly one worker.
|
||||
for (int j = 0; j < numTasks; ++j) {
|
||||
MPConstraint constraint = solver.makeConstraint(1, 1, "");
|
||||
for (int i = 0; i < numWorkers; ++i) {
|
||||
constraint.setCoefficient(x[i][j], 1);
|
||||
}
|
||||
}
|
||||
// [END constraints]
|
||||
|
||||
// Objective
|
||||
// [START objective]
|
||||
MPObjective objective = solver.objective();
|
||||
for (int i = 0; i < numWorkers; ++i) {
|
||||
for (int j = 0; j < numTasks; ++j) {
|
||||
objective.setCoefficient(x[i][j], costs[i][j]);
|
||||
}
|
||||
}
|
||||
objective.setMinimization();
|
||||
// [END objective]
|
||||
|
||||
// Solve
|
||||
// [START solve]
|
||||
MPSolver.ResultStatus resultStatus = solver.solve();
|
||||
// [END solve]
|
||||
|
||||
// Print solution.
|
||||
// [START print_solution]
|
||||
// Check that the problem has a feasible solution.
|
||||
if (resultStatus == MPSolver.ResultStatus.OPTIMAL
|
||||
|| resultStatus == MPSolver.ResultStatus.FEASIBLE) {
|
||||
System.out.println("Total cost: " + objective.value() + "\n");
|
||||
for (int i = 0; i < numWorkers; ++i) {
|
||||
for (int j = 0; j < numTasks; ++j) {
|
||||
// Test if x[i][j] is 0 or 1 (with tolerance for floating point
|
||||
// arithmetic).
|
||||
if (x[i][j].solutionValue() > 0.5) {
|
||||
System.out.println(
|
||||
"Worker " + i + " assigned to task " + j + ". Cost = " + costs[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
System.err.println("No solution found.");
|
||||
}
|
||||
// [END print_solution]
|
||||
}
|
||||
|
||||
private AssignmentMip() {}
|
||||
}
|
||||
// [END program]
|
||||
118
ortools/linear_solver/samples/assignment_mip.cc
Normal file
118
ortools/linear_solver/samples/assignment_mip.cc
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright 2010-2018 Google LLC
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// [START program]
|
||||
// [START import]
|
||||
#include <vector>
|
||||
|
||||
#include "ortools/base/logging.h"
|
||||
#include "ortools/linear_solver/linear_solver.h"
|
||||
// [END import]
|
||||
|
||||
namespace operations_research {
|
||||
void IntegerProgrammingExample() {
|
||||
// Data
|
||||
// [START data_model]
|
||||
const std::vector<std::vector<double>> costs{
|
||||
{90, 80, 75, 70}, {35, 85, 55, 65}, {125, 95, 90, 95},
|
||||
{45, 110, 95, 115}, {50, 100, 90, 100},
|
||||
};
|
||||
const int num_workers = costs.size();
|
||||
const int num_tasks = costs[0].size();
|
||||
// [END data_model]
|
||||
|
||||
// Solver
|
||||
// [START solver]
|
||||
// Create the mip solver with the CBC backend.
|
||||
MPSolver solver("simple_mip_program",
|
||||
MPSolver::CBC_MIXED_INTEGER_PROGRAMMING);
|
||||
// [END solver]
|
||||
|
||||
// Variables
|
||||
// [START variables]
|
||||
// x[i][j] is an array of 0-1 variables, which will be 1
|
||||
// if worker i is assigned to task j.
|
||||
std::vector<std::vector<const MPVariable*>> x(
|
||||
num_workers, std::vector<const MPVariable*>(num_tasks));
|
||||
for (int i = 0; i < num_workers; ++i) {
|
||||
for (int j = 0; j < num_tasks; ++j) {
|
||||
x[i][j] = solver.MakeIntVar(0, 1, "");
|
||||
}
|
||||
}
|
||||
// [END variables]
|
||||
|
||||
// Constraints
|
||||
// [START constraints]
|
||||
// Each worker is assigned to at most one task.
|
||||
for (int i = 0; i < num_workers; ++i) {
|
||||
LinearExpr worker_sum;
|
||||
for (int j = 0; j < num_tasks; ++j) {
|
||||
worker_sum += x[i][j];
|
||||
}
|
||||
solver.MakeRowConstraint(worker_sum <= 1.0);
|
||||
}
|
||||
// Each task is assigned to exactly one worker.
|
||||
for (int j = 0; j < num_tasks; ++j) {
|
||||
LinearExpr task_sum;
|
||||
for (int i = 0; i < num_workers; ++i) {
|
||||
task_sum += x[i][j];
|
||||
}
|
||||
solver.MakeRowConstraint(task_sum == 1.0);
|
||||
}
|
||||
// [END constraints]
|
||||
|
||||
// Objective.
|
||||
// [START objective]
|
||||
MPObjective* const objective = solver.MutableObjective();
|
||||
for (int i = 0; i < num_workers; ++i) {
|
||||
for (int j = 0; j < num_tasks; ++j) {
|
||||
objective->SetCoefficient(x[i][j], costs[i][j]);
|
||||
}
|
||||
}
|
||||
objective->SetMinimization();
|
||||
// [END objective]
|
||||
|
||||
// Solve
|
||||
// [START solve]
|
||||
const MPSolver::ResultStatus result_status = solver.Solve();
|
||||
// [END solve]
|
||||
|
||||
// Print solution.
|
||||
// [START print_solution]
|
||||
// Check that the problem has a feasible solution.
|
||||
if (result_status != MPSolver::OPTIMAL &
|
||||
result_status != MPSolver::FEASIBLE) {
|
||||
LOG(FATAL) << "No solution found.";
|
||||
}
|
||||
|
||||
LOG(INFO) << "Total cost = " << objective->Value() << "\n\n";
|
||||
|
||||
for (int i = 0; i < num_workers; ++i) {
|
||||
for (int j = 0; j < num_tasks; ++j) {
|
||||
// Test if x[i][j] is 0 or 1 (with tolerance for floating point
|
||||
// arithmetic).
|
||||
if (x[i][j]->solution_value() > 0.5) {
|
||||
LOG(INFO) << "Worker " << i << " assigned to task " << j
|
||||
<< ". Cost = " << costs[i][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
// [END print_solution]
|
||||
}
|
||||
} // namespace operations_research
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
operations_research::IntegerProgrammingExample();
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
// [END program]
|
||||
91
ortools/linear_solver/samples/assignment_mip.py
Normal file
91
ortools/linear_solver/samples/assignment_mip.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# Copyright 2010-2018 Google LLC
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
"""MIP example that solves an assignment problem."""
|
||||
# [START program]
|
||||
# [START import]
|
||||
from ortools.linear_solver import pywraplp
|
||||
# [END import]
|
||||
|
||||
|
||||
def main():
|
||||
# Data
|
||||
# [START data_model]
|
||||
costs = [
|
||||
[90, 80, 75, 70],
|
||||
[35, 85, 55, 65],
|
||||
[125, 95, 90, 95],
|
||||
[45, 110, 95, 115],
|
||||
[50, 100, 90, 100],
|
||||
]
|
||||
num_workers = len(costs)
|
||||
num_tasks = len(costs[0])
|
||||
# [END data_model]
|
||||
|
||||
# Solver
|
||||
# [START solver]
|
||||
# Create the mip solver with the CBC backend.
|
||||
solver = pywraplp.Solver('simple_mip_program',
|
||||
pywraplp.Solver.CBC_MIXED_INTEGER_PROGRAMMING)
|
||||
# [END solver]
|
||||
|
||||
# Variables
|
||||
# [START variables]
|
||||
# x[i, j] is an array of 0-1 variables, which will be 1
|
||||
# if worker i is assigned to task j.
|
||||
x = {}
|
||||
for i in range(num_workers):
|
||||
for j in range(num_tasks):
|
||||
x[i, j] = solver.IntVar(0, 1, '')
|
||||
# [END variables]
|
||||
|
||||
# Constraints
|
||||
# [START constraints]
|
||||
# Each worker is assigned to at most 1 task.
|
||||
for i in range(num_workers):
|
||||
solver.Add(solver.Sum([x[i, j] for j in range(num_tasks)]) <= 1)
|
||||
|
||||
# Each task is assigned to exactly one worker.
|
||||
for j in range(num_tasks):
|
||||
solver.Add(solver.Sum([x[i, j] for i in range(num_workers)]) == 1)
|
||||
# [END constraints]
|
||||
|
||||
# Objective
|
||||
# [START objective]
|
||||
objective_terms = []
|
||||
for i in range(num_workers):
|
||||
for j in range(num_tasks):
|
||||
objective_terms.append(costs[i][j] * x[i, j])
|
||||
solver.Minimize(solver.Sum(objective_terms))
|
||||
# [END objective]
|
||||
|
||||
# Solve
|
||||
# [START solve]
|
||||
status = solver.Solve()
|
||||
# [END solve]
|
||||
|
||||
# Print solution.
|
||||
# [START print_solution]
|
||||
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
|
||||
print('Total cost = ', solver.Objective().Value(), '\n')
|
||||
for i in range(num_workers):
|
||||
for j in range(num_tasks):
|
||||
# Test if x[i,j] is 1 (with tolerance for floating point arithmetic).
|
||||
if x[i, j].solution_value() > 0.5:
|
||||
print('Worker %d assigned to task %d. Cost = %d' %
|
||||
(i, j, costs[i][j]))
|
||||
# [END print_solution]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
# [END program]
|
||||
Reference in New Issue
Block a user