# Assignment with Teams of Workers

There are many versions of the assignment problem, which have additional constraints on the workers or tasks. In the next example, six workers are divided into two teams, and each team can perform at most two tasks.

The following sections present a Python program that solves this problem using the CP-SAT or the MIP solver. For a solution using the min cost flow solver, see the section Assignment with teams.

## CP-SAT solution

First, let's take a look at the CP-SAT solution to the problem.

### Import the libraries

The following code imports the required library.

### Python

`from ortools.sat.python import cp_model`

### C++

```#include <stdlib.h>

#include <numeric>
#include <vector>

#include "absl/strings/str_format.h"
#include "ortools/base/logging.h"
#include "ortools/sat/cp_model.h"
#include "ortools/sat/cp_model.pb.h"
#include "ortools/sat/cp_model_solver.h"
```

### Java

```import com.google.ortools.Loader;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;```

### C#

```using System;
using System.Collections.Generic;
using System.Linq;

### Define the data

The following code creates the data for the program.

### Python

```costs = [
[90, 76, 75, 70],
[35, 85, 55, 65],
[125, 95, 90, 105],
[45, 110, 95, 115],
[60, 105, 80, 75],
[45, 65, 110, 95],
]
num_workers = len(costs)

team1 = [0, 2, 4]
team2 = [1, 3, 5]
# Maximum total of tasks for any team
team_max = 2```

### C++

```const std::vector<std::vector<int>> costs = {{
{{90, 76, 75, 70}},
{{35, 85, 55, 65}},
{{125, 95, 90, 105}},
{{45, 110, 95, 115}},
{{60, 105, 80, 75}},
{{45, 65, 110, 95}},
}};
const int num_workers = static_cast<int>(costs.size());
std::vector<int> all_workers(num_workers);
std::iota(all_workers.begin(), all_workers.end(), 0);

const std::vector<int> team1 = {{0, 2, 4}};
const std::vector<int> team2 = {{1, 3, 5}};
// Maximum total of tasks for any team
const int team_max = 2;```

### Java

```int[][] costs = {
{90, 76, 75, 70},
{35, 85, 55, 65},
{125, 95, 90, 105},
{45, 110, 95, 115},
{60, 105, 80, 75},
{45, 65, 110, 95},
};
final int numWorkers = costs.length;

final int[] allWorkers = IntStream.range(0, numWorkers).toArray();

final int[] team1 = {0, 2, 4};
final int[] team2 = {1, 3, 5};
// Maximum total of tasks for any team
final int teamMax = 2;```

### C#

```int[,] costs = {
{ 90, 76, 75, 70 },   { 35, 85, 55, 65 },  { 125, 95, 90, 105 },
{ 45, 110, 95, 115 }, { 60, 105, 80, 75 }, { 45, 65, 110, 95 },
};
int numWorkers = costs.GetLength(0);

int[] allWorkers = Enumerable.Range(0, numWorkers).ToArray();

int[] team1 = { 0, 2, 4 };
int[] team2 = { 1, 3, 5 };
// Maximum total of tasks for any team
int teamMax = 2;```

### Create the model

The following code creates the model.

### Python

`model = cp_model.CpModel()`

### C++

`CpModelBuilder cp_model;`

### Java

`CpModel model = new CpModel();`

### C#

`CpModel model = new CpModel();`

### Create the variables

The following code creates an array of variables for the problem.

### Python

```x = {}
for worker in range(num_workers):

### C++

```// x[i][j] is an array of Boolean variables. x[i][j] is true
// if worker i is assigned to task j.
std::vector<std::vector<BoolVar>> x(num_workers,
for (int worker : all_workers) {
}
}```

### Java

```Literal[][] x = new Literal[numWorkers][numTasks];
// Variables in a 1-dim array.
for (int worker : allWorkers) {
}
}```

### C#

```BoolVar[,] x = new BoolVar[numWorkers, numTasks];
foreach (int worker in allWorkers)
{
{
}
}```

There is one variable for each pair of a worker and task. Note that the workers are numbered `0 - 5`, while the tasks are numbered `0 - 3`, unlike in the original example, in which all nodes had to be numbered differently, as required by the min cost flow solver.

The following code creates the constraints for the program.

### Python

```# Each worker is assigned to at most one task.
for worker in range(num_workers):

# Each task is assigned to exactly one worker.

# Each team takes at most two tasks.
for worker in team1:

for worker in team2:

### C++

```// Each worker is assigned to at most one task.
for (int worker : all_workers) {
}
// Each task is assigned to exactly one worker.
for (int worker : all_workers) {
}
}

// Each team takes at most two tasks.
for (int worker : team1) {
}
}

for (int worker : team2) {
}
}

### Java

```// Each worker is assigned to at most one task.
for (int worker : allWorkers) {
}
}

// Each task is assigned to exactly one worker.
List<Literal> workers = new ArrayList<>();
for (int worker : allWorkers) {
}
}

// Each team takes at most two tasks.
for (int worker : team1) {
}
}

for (int worker : team2) {
}
}

### C#

```// Each worker is assigned to at most one task.
foreach (int worker in allWorkers)
{
{
}
}

// Each task is assigned to exactly one worker.
{
List<ILiteral> workers = new List<ILiteral>();
foreach (int worker in allWorkers)
{
}
}

// Each team takes at most two tasks.
foreach (int worker in team1)
{
{
}
}

foreach (int worker in team2)
{
{
}
}

### Create the objective

The following code creates the objective function.

### Python

```objective_terms = []
for worker in range(num_workers):
model.Minimize(sum(objective_terms))```

### C++

```LinearExpr total_cost;
for (int worker : all_workers) {
}
}
cp_model.Minimize(total_cost);```

### Java

```LinearExprBuilder obj = LinearExpr.newBuilder();
for (int worker : allWorkers) {
}
}
model.minimize(obj);```

### C#

```LinearExprBuilder obj = LinearExpr.NewBuilder();
foreach (int worker in allWorkers)
{
{
}
}
model.Minimize(obj);```

The value of the objective function is the total cost over all variables that are assigned the value 1 by the solver.

### Invoke the solver

The following code invokes the solver and displays the results.

### Python

```solver = cp_model.CpSolver()
status = solver.Solve(model)```

### C++

`const CpSolverResponse response = Solve(cp_model.Build());`

### Java

```CpSolver solver = new CpSolver();
CpSolverStatus status = solver.solve(model);```

### C#

```CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Console.WriteLine(\$"Solve status: {status}");```

### Display the results

Now, we can print the solution.

### Python

```if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
print(f'Total cost = {solver.ObjectiveValue()}\n')
for worker in range(num_workers):
else:
print('No solution found.')```

### C++

```if (response.status() == CpSolverStatus::INFEASIBLE) {
LOG(FATAL) << "No solution found.";
}
LOG(INFO) << "Total cost: " << response.objective_value();
LOG(INFO);
for (int worker : all_workers) {
LOG(INFO) << "Worker " << worker << " assigned to task " << task
<< ".  Cost: " << costs[worker][task];
}
}
}```

### Java

```// Check that the problem has a feasible solution.
if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) {
System.out.println("Total cost: " + solver.objectiveValue() + "\n");
for (int worker : allWorkers) {
System.out.println("Worker " + worker + " assigned to task " + task
+ ".  Cost: " + costs[worker][task]);
}
}
}
} else {
System.err.println("No solution found.");
}```

### C#

```// Check that the problem has a feasible solution.
if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
{
Console.WriteLine(\$"Total cost: {solver.ObjectiveValue}\n");
foreach (int worker in allWorkers)
{
{
{
}
}
}
}
else
{
Console.WriteLine("No solution found.");
}```

Here's the output of the program.

```Total cost:  250
Worker 0 assigned to task 2. Cost = 75
Worker 1 assigned to task 0. Cost = 35
Worker 4 assigned to task 3. Cost = 75
Worker 5 assigned to task 1. Cost = 65
Time =  6  milliseconds```

### The entire program

Here is the entire program.

### Python

```"""Solve a simple assignment problem."""
from ortools.sat.python import cp_model

def main():
# Data
costs = [
[90, 76, 75, 70],
[35, 85, 55, 65],
[125, 95, 90, 105],
[45, 110, 95, 115],
[60, 105, 80, 75],
[45, 65, 110, 95],
]
num_workers = len(costs)

team1 = [0, 2, 4]
team2 = [1, 3, 5]
# Maximum total of tasks for any team
team_max = 2

# Model
model = cp_model.CpModel()

# Variables
x = {}
for worker in range(num_workers):

# Constraints
# Each worker is assigned to at most one task.
for worker in range(num_workers):

# Each task is assigned to exactly one worker.

# Each team takes at most two tasks.
for worker in team1:

for worker in team2:

# Objective
objective_terms = []
for worker in range(num_workers):
model.Minimize(sum(objective_terms))

# Solve
solver = cp_model.CpSolver()
status = solver.Solve(model)

# Print solution.
if status == cp_model.OPTIMAL or status == cp_model.FEASIBLE:
print(f'Total cost = {solver.ObjectiveValue()}\n')
for worker in range(num_workers):
else:
print('No solution found.')

if __name__ == '__main__':
main()```

### C++

```// Solve a simple assignment problem.
#include <stdlib.h>

#include <numeric>
#include <vector>

#include "absl/strings/str_format.h"
#include "ortools/base/logging.h"
#include "ortools/sat/cp_model.h"
#include "ortools/sat/cp_model.pb.h"
#include "ortools/sat/cp_model_solver.h"

namespace operations_research {
namespace sat {

void AssignmentTeamsSat() {
// Data
const std::vector<std::vector<int>> costs = {{
{{90, 76, 75, 70}},
{{35, 85, 55, 65}},
{{125, 95, 90, 105}},
{{45, 110, 95, 115}},
{{60, 105, 80, 75}},
{{45, 65, 110, 95}},
}};
const int num_workers = static_cast<int>(costs.size());
std::vector<int> all_workers(num_workers);
std::iota(all_workers.begin(), all_workers.end(), 0);

const std::vector<int> team1 = {{0, 2, 4}};
const std::vector<int> team2 = {{1, 3, 5}};
// Maximum total of tasks for any team
const int team_max = 2;

// Model
CpModelBuilder cp_model;

// Variables
// x[i][j] is an array of Boolean variables. x[i][j] is true
// if worker i is assigned to task j.
std::vector<std::vector<BoolVar>> x(num_workers,
for (int worker : all_workers) {
}
}

// Constraints
// Each worker is assigned to at most one task.
for (int worker : all_workers) {
}
// Each task is assigned to exactly one worker.
for (int worker : all_workers) {
}
}

// Each team takes at most two tasks.
for (int worker : team1) {
}
}

for (int worker : team2) {
}
}

// Objective
LinearExpr total_cost;
for (int worker : all_workers) {
}
}
cp_model.Minimize(total_cost);

// Solve
const CpSolverResponse response = Solve(cp_model.Build());

// Print solution.
if (response.status() == CpSolverStatus::INFEASIBLE) {
LOG(FATAL) << "No solution found.";
}
LOG(INFO) << "Total cost: " << response.objective_value();
LOG(INFO);
for (int worker : all_workers) {
LOG(INFO) << "Worker " << worker << " assigned to task " << task
<< ".  Cost: " << costs[worker][task];
}
}
}
}
}  // namespace sat
}  // namespace operations_research

int main(int argc, char** argv) {
operations_research::sat::AssignmentTeamsSat();
return EXIT_SUCCESS;
}```

### Java

```// CP-SAT example that solves an assignment problem.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

/** Assignment problem. */
public class AssignmentTeamsSat {
public static void main(String[] args) {
// Data
int[][] costs = {
{90, 76, 75, 70},
{35, 85, 55, 65},
{125, 95, 90, 105},
{45, 110, 95, 115},
{60, 105, 80, 75},
{45, 65, 110, 95},
};
final int numWorkers = costs.length;

final int[] allWorkers = IntStream.range(0, numWorkers).toArray();

final int[] team1 = {0, 2, 4};
final int[] team2 = {1, 3, 5};
// Maximum total of tasks for any team
final int teamMax = 2;

// Model
CpModel model = new CpModel();

// Variables
// Variables in a 1-dim array.
for (int worker : allWorkers) {
}
}

// Constraints
// Each worker is assigned to at most one task.
for (int worker : allWorkers) {
}
}

// Each task is assigned to exactly one worker.
List<Literal> workers = new ArrayList<>();
for (int worker : allWorkers) {
}
}

// Each team takes at most two tasks.
for (int worker : team1) {
}
}

for (int worker : team2) {
}
}

// Objective
LinearExprBuilder obj = LinearExpr.newBuilder();
for (int worker : allWorkers) {
}
}
model.minimize(obj);

// Solve
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.solve(model);

// Print solution.
// Check that the problem has a feasible solution.
if (status == CpSolverStatus.OPTIMAL || status == CpSolverStatus.FEASIBLE) {
System.out.println("Total cost: " + solver.objectiveValue() + "\n");
for (int worker : allWorkers) {
System.out.println("Worker " + worker + " assigned to task " + task
+ ".  Cost: " + costs[worker][task]);
}
}
}
} else {
System.err.println("No solution found.");
}
}

private AssignmentTeamsSat() {}
}
```

### C#

```using System;
using System.Collections.Generic;
using System.Linq;

public class AssignmentTeamsSat
{
public static void Main(String[] args)
{
// Data.
int[,] costs = {
{ 90, 76, 75, 70 },   { 35, 85, 55, 65 },  { 125, 95, 90, 105 },
{ 45, 110, 95, 115 }, { 60, 105, 80, 75 }, { 45, 65, 110, 95 },
};
int numWorkers = costs.GetLength(0);

int[] allWorkers = Enumerable.Range(0, numWorkers).ToArray();

int[] team1 = { 0, 2, 4 };
int[] team2 = { 1, 3, 5 };
// Maximum total of tasks for any team
int teamMax = 2;

// Model.
CpModel model = new CpModel();

// Variables.
BoolVar[,] x = new BoolVar[numWorkers, numTasks];
foreach (int worker in allWorkers)
{
{
}
}

// Constraints
// Each worker is assigned to at most one task.
foreach (int worker in allWorkers)
{
{
}
}

// Each task is assigned to exactly one worker.
{
List<ILiteral> workers = new List<ILiteral>();
foreach (int worker in allWorkers)
{
}
}

// Each team takes at most two tasks.
foreach (int worker in team1)
{
{
}
}

foreach (int worker in team2)
{
{
}
}

// Objective
LinearExprBuilder obj = LinearExpr.NewBuilder();
foreach (int worker in allWorkers)
{
{
}
}
model.Minimize(obj);

// Solve
CpSolver solver = new CpSolver();
CpSolverStatus status = solver.Solve(model);
Console.WriteLine(\$"Solve status: {status}");

// Print solution.
// Check that the problem has a feasible solution.
if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
{
Console.WriteLine(\$"Total cost: {solver.ObjectiveValue}\n");
foreach (int worker in allWorkers)
{
{
{
}
}
}
}
else
{
Console.WriteLine("No solution found.");
}

Console.WriteLine("Statistics");
Console.WriteLine(\$"  - conflicts : {solver.NumConflicts()}");
Console.WriteLine(\$"  - branches  : {solver.NumBranches()}");
Console.WriteLine(\$"  - wall time : {solver.WallTime()}s");
}
}```

## MIP solution

Next, we describe a solution to this assignment problem using the MIP solver.

### Import the libraries

The following code imports the required library.

### Python

`from ortools.linear_solver import pywraplp`

### C++

```#include <cstdint>
#include <memory>
#include <numeric>
#include <vector>

#include "absl/strings/str_format.h"
#include "ortools/base/logging.h"
#include "ortools/linear_solver/linear_solver.h"```

### Java

```import com.google.ortools.Loader;
import java.util.stream.IntStream;```

### C#

```using System;
using System.Collections.Generic;
using System.Linq;

### Define the data

The following code creates the data for the program.

### Python

```costs = [
[90, 76, 75, 70],
[35, 85, 55, 65],
[125, 95, 90, 105],
[45, 110, 95, 115],
[60, 105, 80, 75],
[45, 65, 110, 95],
]
num_workers = len(costs)

team1 = [0, 2, 4]
team2 = [1, 3, 5]
# Maximum total of tasks for any team
team_max = 2```

### C++

```const std::vector<std::vector<int64_t>> costs = {{
{{90, 76, 75, 70}},
{{35, 85, 55, 65}},
{{125, 95, 90, 105}},
{{45, 110, 95, 115}},
{{60, 105, 80, 75}},
{{45, 65, 110, 95}},
}};
const int num_workers = costs.size();
std::vector<int> all_workers(num_workers);
std::iota(all_workers.begin(), all_workers.end(), 0);

const std::vector<int64_t> team1 = {{0, 2, 4}};
const std::vector<int64_t> team2 = {{1, 3, 5}};
// Maximum total of tasks for any team
const int team_max = 2;```

### Java

```double[][] costs = {
{90, 76, 75, 70},
{35, 85, 55, 65},
{125, 95, 90, 105},
{45, 110, 95, 115},
{60, 105, 80, 75},
{45, 65, 110, 95},
};
int numWorkers = costs.length;

final int[] allWorkers = IntStream.range(0, numWorkers).toArray();

final int[] team1 = {0, 2, 4};
final int[] team2 = {1, 3, 5};
// Maximum total of tasks for any team
final int teamMax = 2;```

### C#

```int[,] costs = {
{ 90, 76, 75, 70 },   { 35, 85, 55, 65 },  { 125, 95, 90, 105 },
{ 45, 110, 95, 115 }, { 60, 105, 80, 75 }, { 45, 65, 110, 95 },
};
int numWorkers = costs.GetLength(0);

int[] allWorkers = Enumerable.Range(0, numWorkers).ToArray();

int[] team1 = { 0, 2, 4 };
int[] team2 = { 1, 3, 5 };
// Maximum total of tasks for any team
int teamMax = 2;```

### Declare the solver

The following code creates the solver.

### Python

```# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
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#

```Solver solver = Solver.CreateSolver("SCIP");
if (solver is null)
{
return;
}```

### Create the variables

The following code creates an array of variables for the problem.

### Python

```# x[i, j] is an array of 0-1 variables, which will be 1
# if worker i is assigned to task j.
x = {}
for worker in range(num_workers):

### C++

```// 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(
for (int worker : all_workers) {
}
}```

### Java

```// x[i][j] is an array of 0-1 variables, which will be 1
// if worker i is assigned to task j.
for (int worker : allWorkers) {
}
}```

### C#

```// 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[numWorkers, numTasks];
foreach (int worker in allWorkers)
{
{
}
}```

The following code creates the constraints for the program.

### Python

```# Each worker is assigned at most 1 task.
for worker in range(num_workers):

# Each task is assigned to exactly one worker.
solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)

# Each team takes at most two tasks.
for worker in team1:

for worker in team2:

### C++

```// Each worker is assigned to at most one task.
for (int worker : all_workers) {
LinearExpr worker_sum;
}
solver->MakeRowConstraint(worker_sum <= 1.0);
}
// Each task is assigned to exactly one worker.
for (int worker : all_workers) {
}
}

// Each team takes at most two tasks.
for (int worker : team1) {
}
}

for (int worker : team2) {
}
}

### Java

```// Each worker is assigned to at most one task.
for (int worker : allWorkers) {
MPConstraint constraint = solver.makeConstraint(0, 1, "");
}
}
// Each task is assigned to exactly one worker.
MPConstraint constraint = solver.makeConstraint(1, 1, "");
for (int worker : allWorkers) {
}
}

// Each team takes at most two tasks.
MPConstraint team1Tasks = solver.makeConstraint(0, teamMax, "");
for (int worker : team1) {
}
}

MPConstraint team2Tasks = solver.makeConstraint(0, teamMax, "");
for (int worker : team2) {
}
}```

### C#

```// Each worker is assigned to at most one task.
foreach (int worker in allWorkers)
{
Constraint constraint = solver.MakeConstraint(0, 1, "");
{
}
}
// Each task is assigned to exactly one worker.
{
Constraint constraint = solver.MakeConstraint(1, 1, "");
foreach (int worker in allWorkers)
{
}
}

// Each team takes at most two tasks.
Constraint team1Tasks = solver.MakeConstraint(0, teamMax, "");
foreach (int worker in team1)
{
{
}
}

Constraint team2Tasks = solver.MakeConstraint(0, teamMax, "");
foreach (int worker in team2)
{
{
}
}```

### Create the objective

The following code creates the objective function.

### Python

```objective_terms = []
for worker in range(num_workers):
solver.Minimize(solver.Sum(objective_terms))```

### C++

```MPObjective* const objective = solver->MutableObjective();
for (int worker : all_workers) {
}
}
objective->SetMinimization();```

### Java

```MPObjective objective = solver.objective();
for (int worker : allWorkers) {
}
}
objective.setMinimization();```

### C#

```Objective objective = solver.Objective();
foreach (int worker in allWorkers)
{
{
}
}
objective.SetMinimization();```

### Invoke the solver

The following code invokes the solver and displays the results.

### Python

`status = solver.Solve()`

### C++

`const MPSolver::ResultStatus result_status = solver->Solve();`

### Java

`MPSolver.ResultStatus resultStatus = solver.solve();`

### C#

`Solver.ResultStatus resultStatus = solver.Solve();`

### Display the results

Now, we can print the solution.

### Python

```if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
print(f'Total cost = {solver.Objective().Value()}\n')
for worker in range(num_workers):
else:
print('No solution found.')
print(f'Time = {solver.WallTime()} ms')```

### C++

```// 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 worker : all_workers) {
// Test if x[i][j] is 0 or 1 (with tolerance for floating point
// arithmetic).
LOG(INFO) << "Worker " << worker << " assigned to task " << task
<< ".  Cost: " << costs[worker][task];
}
}
}```

### Java

```// 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 worker : allWorkers) {
// Test if x[i][j] is 0 or 1 (with tolerance for floating point
// arithmetic).
System.out.println("Worker " + worker + " assigned to task " + task
+ ".  Cost: " + costs[worker][task]);
}
}
}
} else {
System.err.println("No solution found.");
}```

### C#

```// Check that the problem has a feasible solution.
if (resultStatus == Solver.ResultStatus.OPTIMAL || resultStatus == Solver.ResultStatus.FEASIBLE)
{
Console.WriteLine(\$"Total cost: {solver.Objective().Value()}\n");
foreach (int worker in allWorkers)
{
{
// Test if x[i, j] is 0 or 1 (with tolerance for floating point
// arithmetic).
{
}
}
}
}
else
{
Console.WriteLine("No solution found.");
}```

Here is the output of the program.

```Minimum cost assignment:  250.0
Worker 0 assigned to task 2. Cost = 75
Worker 1 assigned to task 0. Cost = 35
Worker 4 assigned to task 3. Cost = 75
Worker 5 assigned to task 1. Cost = 65
Time =  6  milliseconds```

### The entire program

Here is the entire program.

### Python

```"""MIP example that solves an assignment problem."""
from ortools.linear_solver import pywraplp

def main():
# Data
costs = [
[90, 76, 75, 70],
[35, 85, 55, 65],
[125, 95, 90, 105],
[45, 110, 95, 115],
[60, 105, 80, 75],
[45, 65, 110, 95],
]
num_workers = len(costs)

team1 = [0, 2, 4]
team2 = [1, 3, 5]
# Maximum total of tasks for any team
team_max = 2

# Solver
# Create the mip solver with the SCIP backend.
solver = pywraplp.Solver.CreateSolver('SCIP')
if not solver:
return

# 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 worker in range(num_workers):

# Constraints
# Each worker is assigned at most 1 task.
for worker in range(num_workers):

# Each task is assigned to exactly one worker.
solver.Sum([x[worker, task] for worker in range(num_workers)]) == 1)

# Each team takes at most two tasks.
for worker in team1:

for worker in team2:

# Objective
objective_terms = []
for worker in range(num_workers):
solver.Minimize(solver.Sum(objective_terms))

# Solve
status = solver.Solve()

# Print solution.
if status == pywraplp.Solver.OPTIMAL or status == pywraplp.Solver.FEASIBLE:
print(f'Total cost = {solver.Objective().Value()}\n')
for worker in range(num_workers):
else:
print('No solution found.')
print(f'Time = {solver.WallTime()} ms')

if __name__ == '__main__':
main()```

### C++

```// Solve a simple assignment problem.
#include <cstdint>
#include <memory>
#include <numeric>
#include <vector>

#include "absl/strings/str_format.h"
#include "ortools/base/logging.h"
#include "ortools/linear_solver/linear_solver.h"

namespace operations_research {
void AssignmentTeamsMip() {
// Data
const std::vector<std::vector<int64_t>> costs = {{
{{90, 76, 75, 70}},
{{35, 85, 55, 65}},
{{125, 95, 90, 105}},
{{45, 110, 95, 115}},
{{60, 105, 80, 75}},
{{45, 65, 110, 95}},
}};
const int num_workers = costs.size();
std::vector<int> all_workers(num_workers);
std::iota(all_workers.begin(), all_workers.end(), 0);

const std::vector<int64_t> team1 = {{0, 2, 4}};
const std::vector<int64_t> team2 = {{1, 3, 5}};
// Maximum total of tasks for any team
const int team_max = 2;

// Solver
// Create the mip solver with the SCIP backend.
std::unique_ptr<MPSolver> solver(MPSolver::CreateSolver("SCIP"));
if (!solver) {
LOG(WARNING) << "SCIP solver unavailable.";
return;
}

// 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(
for (int worker : all_workers) {
}
}

// Constraints
// Each worker is assigned to at most one task.
for (int worker : all_workers) {
LinearExpr worker_sum;
}
solver->MakeRowConstraint(worker_sum <= 1.0);
}
// Each task is assigned to exactly one worker.
for (int worker : all_workers) {
}
}

// Each team takes at most two tasks.
for (int worker : team1) {
}
}

for (int worker : team2) {
}
}

// Objective.
MPObjective* const objective = solver->MutableObjective();
for (int worker : all_workers) {
}
}
objective->SetMinimization();

// Solve
const MPSolver::ResultStatus result_status = solver->Solve();

// 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 worker : all_workers) {
// Test if x[i][j] is 0 or 1 (with tolerance for floating point
// arithmetic).
LOG(INFO) << "Worker " << worker << " assigned to task " << task
<< ".  Cost: " << costs[worker][task];
}
}
}
}
}  // namespace operations_research

int main(int argc, char** argv) {
operations_research::AssignmentTeamsMip();
return EXIT_SUCCESS;
}```

### Java

```package com.google.ortools.linearsolver.samples;
import java.util.stream.IntStream;

/** MIP example that solves an assignment problem. */
public class AssignmentTeamsMip {
public static void main(String[] args) {
// Data
double[][] costs = {
{90, 76, 75, 70},
{35, 85, 55, 65},
{125, 95, 90, 105},
{45, 110, 95, 115},
{60, 105, 80, 75},
{45, 65, 110, 95},
};
int numWorkers = costs.length;

final int[] allWorkers = IntStream.range(0, numWorkers).toArray();

final int[] team1 = {0, 2, 4};
final int[] team2 = {1, 3, 5};
// Maximum total of tasks for any team
final int teamMax = 2;

// Solver
// 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;
}

// Variables
// x[i][j] is an array of 0-1 variables, which will be 1
// if worker i is assigned to task j.
for (int worker : allWorkers) {
}
}

// Constraints
// Each worker is assigned to at most one task.
for (int worker : allWorkers) {
MPConstraint constraint = solver.makeConstraint(0, 1, "");
}
}
// Each task is assigned to exactly one worker.
MPConstraint constraint = solver.makeConstraint(1, 1, "");
for (int worker : allWorkers) {
}
}

// Each team takes at most two tasks.
MPConstraint team1Tasks = solver.makeConstraint(0, teamMax, "");
for (int worker : team1) {
}
}

MPConstraint team2Tasks = solver.makeConstraint(0, teamMax, "");
for (int worker : team2) {
}
}

// Objective
MPObjective objective = solver.objective();
for (int worker : allWorkers) {
}
}
objective.setMinimization();

// Solve
MPSolver.ResultStatus resultStatus = solver.solve();

// 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 worker : allWorkers) {
// Test if x[i][j] is 0 or 1 (with tolerance for floating point
// arithmetic).
System.out.println("Worker " + worker + " assigned to task " + task
+ ".  Cost: " + costs[worker][task]);
}
}
}
} else {
System.err.println("No solution found.");
}
}

private AssignmentTeamsMip() {}
}```

### C#

```using System;
using System.Collections.Generic;
using System.Linq;

public class AssignmentTeamsMip
{
static void Main()
{
// Data.
int[,] costs = {
{ 90, 76, 75, 70 },   { 35, 85, 55, 65 },  { 125, 95, 90, 105 },
{ 45, 110, 95, 115 }, { 60, 105, 80, 75 }, { 45, 65, 110, 95 },
};
int numWorkers = costs.GetLength(0);

int[] allWorkers = Enumerable.Range(0, numWorkers).ToArray();

int[] team1 = { 0, 2, 4 };
int[] team2 = { 1, 3, 5 };
// Maximum total of tasks for any team
int teamMax = 2;

// Solver.
Solver solver = Solver.CreateSolver("SCIP");
if (solver is null)
{
return;
}

// 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[numWorkers, numTasks];
foreach (int worker in allWorkers)
{
{
}
}

// Constraints
// Each worker is assigned to at most one task.
foreach (int worker in allWorkers)
{
Constraint constraint = solver.MakeConstraint(0, 1, "");
{
}
}
// Each task is assigned to exactly one worker.
{
Constraint constraint = solver.MakeConstraint(1, 1, "");
foreach (int worker in allWorkers)
{
}
}

// Each team takes at most two tasks.
Constraint team1Tasks = solver.MakeConstraint(0, teamMax, "");
foreach (int worker in team1)
{
{
}
}

Constraint team2Tasks = solver.MakeConstraint(0, teamMax, "");
foreach (int worker in team2)
{
{
}
}

// Objective
Objective objective = solver.Objective();
foreach (int worker in allWorkers)
{
{
}
}
objective.SetMinimization();

// Solve
Solver.ResultStatus resultStatus = solver.Solve();

// Print solution.
// Check that the problem has a feasible solution.
if (resultStatus == Solver.ResultStatus.OPTIMAL || resultStatus == Solver.ResultStatus.FEASIBLE)
{
Console.WriteLine(\$"Total cost: {solver.Objective().Value()}\n");
foreach (int worker in allWorkers)
{
{
// Test if x[i, j] is 0 or 1 (with tolerance for floating point
// arithmetic).
{