Files
ortools-clone/examples/dotnet/crew.cs
Corentin Le Molgat 42d7c276ab dotnet: rework example layout
- Fix examples using MPConstraint::Activity instead of MPSolver
- Move all examples to exmaples/dotnet
- remove netfx sub-directories
- Add all examples to target test_dotnet
  - still few disabled since they are too long
- Add tools/generate_examples_csproj.sh to generate .*proj files
2018-08-30 11:58:47 +02:00

273 lines
7.3 KiB
C#

//
// Copyright 2012 Hakan Kjellerstrand
//
// 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 System.Collections;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Google.OrTools.ConstraintSolver;
public class Crew
{
/**
*
* Crew allocation problem in Google CP Solver.
*
* From Gecode example crew
* examples/crew.cc
* """
* Example: Airline crew allocation
*
* Assign 20 flight attendants to 10 flights. Each flight needs a certain
* number of cabin crew, and they have to speak certain languages.
* Every cabin crew member has two flights off after an attended flight.
* """
*
* Also see http://www.hakank.org/or-tools/crew.pl
*
*/
private static void Solve(int sols = 1, int minimize = 0)
{
Solver solver = new Solver("Crew");
//
// Data
//
string[] names = {"Tom",
"David",
"Jeremy",
"Ron",
"Joe",
"Bill",
"Fred",
"Bob",
"Mario",
"Ed",
"Carol",
"Janet",
"Tracy",
"Marilyn",
"Carolyn",
"Cathy",
"Inez",
"Jean",
"Heather",
"Juliet"};
int num_persons = names.Length;
//
// Attributes of the crew
//
int[,] attributes = {
// steward, hostess, french, spanish, german
{1,0,0,0,1}, // Tom = 0
{1,0,0,0,0}, // David = 1
{1,0,0,0,1}, // Jeremy = 2
{1,0,0,0,0}, // Ron = 3
{1,0,0,1,0}, // Joe = 4
{1,0,1,1,0}, // Bill = 5
{1,0,0,1,0}, // Fred = 6
{1,0,0,0,0}, // Bob = 7
{1,0,0,1,1}, // Mario = 8
{1,0,0,0,0}, // Ed = 9
{0,1,0,0,0}, // Carol = 10
{0,1,0,0,0}, // Janet = 11
{0,1,0,0,0}, // Tracy = 12
{0,1,0,1,1}, // Marilyn = 13
{0,1,0,0,0}, // Carolyn = 14
{0,1,0,0,0}, // Cathy = 15
{0,1,1,1,1}, // Inez = 16
{0,1,1,0,0}, // Jean = 17
{0,1,0,1,1}, // Heather = 18
{0,1,1,0,0} // Juliet = 19
};
//
// Required number of crew members.
//
// The columns are in the following order:
// staff : Overall number of cabin crew needed
// stewards : How many stewards are required
// hostesses : How many hostesses are required
// french : How many French speaking employees are required
// spanish : How many Spanish speaking employees are required
// german : How many German speaking employees are required
//
int[,] required_crew = {
{4,1,1,1,1,1}, // Flight 1
{5,1,1,1,1,1}, // Flight 2
{5,1,1,1,1,1}, // ..
{6,2,2,1,1,1},
{7,3,3,1,1,1},
{4,1,1,1,1,1},
{5,1,1,1,1,1},
{6,1,1,1,1,1},
{6,2,2,1,1,1}, // ...
{7,3,3,1,1,1} // Flight 10
};
int num_flights = required_crew.GetLength(0);
//
// Decision variables
//
IntVar[,] crew = solver.MakeIntVarMatrix(num_flights, num_persons,
0, 1, "crew");
IntVar[] crew_flat = crew.Flatten();
// number of working persons
IntVar num_working = solver.MakeIntVar(1, num_persons, "num_working");
//
// Constraints
//
// number of working persons
IntVar[] nw = new IntVar[num_persons];
for(int p = 0; p < num_persons; p++) {
IntVar[] tmp = new IntVar[num_flights];
for(int f = 0; f < num_flights; f++) {
tmp[f] = crew[f,p];
}
nw[p] = tmp.Sum() > 0;
}
solver.Add(nw.Sum() == num_working);
for(int f = 0; f < num_flights; f++) {
// size of crew
IntVar[] tmp = new IntVar[num_persons];
for(int p = 0; p < num_persons; p++) {
tmp[p] = crew[f,p];
}
solver.Add(tmp.Sum() == required_crew[f,0]);
// attributes and requirements
for(int a = 0; a < 5; a++) {
IntVar[] tmp2 = new IntVar[num_persons];
for(int p = 0; p < num_persons; p++) {
tmp2[p] = (crew[f,p]*attributes[p,a]).Var();
}
solver.Add(tmp2.Sum() >= required_crew[f,a+1]);
}
}
// after a flight, break for at least two flights
for(int f = 0; f < num_flights - 2; f++) {
for(int i = 0; i < num_persons; i++) {
solver.Add(crew[f,i] + crew[f+1,i] + crew[f+2,i] <= 1);
}
}
// extra contraint: all must work at least two of the flights
/*
for(int p = 0; p < num_persons; p++) {
IntVar[] tmp = new IntVar[num_flights];
for(int f = 0; f < num_flights; f++) {
tmp[f] = crew[f,p];
}
solver.Add(tmp.Sum() >= 2);
}
*/
//
// Search
//
DecisionBuilder db = solver.MakePhase(crew_flat,
Solver.CHOOSE_FIRST_UNBOUND,
Solver.ASSIGN_MIN_VALUE);
if (minimize > 0) {
OptimizeVar obj = num_working.Minimize(1);
solver.NewSearch(db, obj);
} else {
solver.NewSearch(db);
}
int num_solutions = 0;
while (solver.NextSolution()) {
num_solutions++;
Console.WriteLine("Solution #{0}", num_solutions);
Console.WriteLine("Number working: {0}", num_working.Value());
for(int f = 0; f < num_flights; f++) {
for(int p = 0; p < num_persons; p++) {
Console.Write(crew[f,p].Value() + " ");
}
Console.WriteLine();
}
Console.WriteLine("\nFlights: ");
for(int f = 0; f < num_flights; f++) {
Console.Write("Flight #{0}: ", f);
for(int p = 0; p < num_persons; p++) {
if (crew[f, p].Value() == 1) {
Console.Write(names[p] + " ");
}
}
Console.WriteLine();
}
Console.WriteLine("\nCrew:");
for(int p = 0; p < num_persons; p++) {
Console.Write("{0,-10}", names[p]);
for(int f = 0; f < num_flights; f++) {
if (crew[f,p].Value() == 1) {
Console.Write(f + " ");
}
}
Console.WriteLine();
}
Console.WriteLine();
if (num_solutions >= sols) {
break;
}
}
Console.WriteLine("\nSolutions: {0}", solver.Solutions());
Console.WriteLine("WallTime: {0}ms", solver.WallTime());
Console.WriteLine("Failures: {0}", solver.Failures());
Console.WriteLine("Branches: {0} ", solver.Branches());
solver.EndSearch();
}
public static void Main(String[] args)
{
int n = 1;
int min = 0; // > 0 -> minimize num_working
if (args.Length > 0) {
n = Convert.ToInt32(args[0]);
}
if (args.Length > 1) {
min = Convert.ToInt32(args[1]);
}
Solve(n, min);
}
}