Add examples for C#
This commit is contained in:
34
examples/dotnet/OrTools.sln
Normal file
34
examples/dotnet/OrTools.sln
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.26124.0
|
||||
MinimumVisualStudioVersion = 15.0.26124.0
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "examples", "csharp\examples.csproj", "{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Debug|x64.Build.0 = Debug|x64
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Debug|x86.Build.0 = Debug|x86
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Release|x64.ActiveCfg = Release|x64
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Release|x64.Build.0 = Release|x64
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Release|x86.ActiveCfg = Release|x86
|
||||
{0899C5EB-2AD1-49C1-9AB3-735E5B81BF56}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
21
examples/dotnet/README.md
Normal file
21
examples/dotnet/README.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Dotnet Core examples
|
||||
|
||||
The following examples showcase how to use OrTools. The project solution has examples for both C# and F#.
|
||||
|
||||
We recommend that all projects you create target `netcoreapp2.0` as this allows you to compile for various frameworks and keep up-to-date with the latest frameworks.
|
||||
|
||||
Wherever you have ortools installed, be sure to reference the `Google.OrTools.dll` from the project file. You will also need to reference the library folder housing native libraries.
|
||||
|
||||
### Linux
|
||||
To reference a particular folder on linux, you can either: explicitly set the **LD_LIBRARY_PATH**; or create a new configuration file with the path of the library folder in `/etc/ld.so.conf.d/` and then run `sudo ldconfig`. The former will set the path on a system level so that you don't have to use the environment.
|
||||
|
||||
### MacOS
|
||||
To reference a particular folder on linux, you can explicitly set the **DYLD_FALLBACK_LIBRARY_PATH**
|
||||
|
||||
## CSharp
|
||||
|
||||
By default all the examples are compiled in a console applicaiton with the startup object being the **Classname.Main** so that when compiled the entrypoint will be known.
|
||||
|
||||
## FSharp
|
||||
|
||||
TBD
|
||||
293
examples/dotnet/csharp/3_jugs_regular.cs
Normal file
293
examples/dotnet/csharp/3_jugs_regular.cs
Normal file
@@ -0,0 +1,293 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Diagnostics;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class ThreeJugsRegular
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
* Global constraint regular
|
||||
*
|
||||
* This is a translation of MiniZinc's regular constraint (defined in
|
||||
* lib/zinc/globals.mzn), via the Comet code refered above.
|
||||
* All comments are from the MiniZinc code.
|
||||
* """
|
||||
* The sequence of values in array 'x' (which must all be in the range 1..S)
|
||||
* is accepted by the DFA of 'Q' states with input 1..S and transition
|
||||
* function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'
|
||||
* (which must be in 1..Q) and accepting states 'F' (which all must be in
|
||||
* 1..Q). We reserve state 0 to be an always failing state.
|
||||
* """
|
||||
*
|
||||
* x : IntVar array
|
||||
* Q : number of states
|
||||
* S : input_max
|
||||
* d : transition matrix
|
||||
* q0: initial state
|
||||
* F : accepting states
|
||||
*
|
||||
*/
|
||||
static void MyRegular(Solver solver,
|
||||
IntVar[] x,
|
||||
int Q,
|
||||
int S,
|
||||
int[,] d,
|
||||
int q0,
|
||||
int[] F) {
|
||||
|
||||
|
||||
|
||||
Debug.Assert(Q > 0, "regular: 'Q' must be greater than zero");
|
||||
Debug.Assert(S > 0, "regular: 'S' must be greater than zero");
|
||||
|
||||
// d2 is the same as d, except we add one extra transition for
|
||||
// each possible input; each extra transition is from state zero
|
||||
// to state zero. This allows us to continue even if we hit a
|
||||
// non-accepted input.
|
||||
int[][] d2 = new int[Q+1][];
|
||||
for(int i = 0; i <= Q; i++) {
|
||||
int[] row = new int[S];
|
||||
for(int j = 0; j < S; j++) {
|
||||
if (i == 0) {
|
||||
row[j] = 0;
|
||||
} else {
|
||||
row[j] = d[i-1,j];
|
||||
}
|
||||
}
|
||||
d2[i] = row;
|
||||
}
|
||||
|
||||
int[] d2_flatten = (from i in Enumerable.Range(0, Q+1)
|
||||
from j in Enumerable.Range(0, S)
|
||||
select d2[i][j]).ToArray();
|
||||
|
||||
// If x has index set m..n, then a[m-1] holds the initial state
|
||||
// (q0), and a[i+1] holds the state we're in after processing
|
||||
// x[i]. If a[n] is in F, then we succeed (ie. accept the
|
||||
// string).
|
||||
int m = 0;
|
||||
int n = x.Length;
|
||||
|
||||
IntVar[] a = solver.MakeIntVarArray(n+1-m, 0,Q+1, "a");
|
||||
// Check that the final state is in F
|
||||
solver.Add(a[a.Length-1].Member(F));
|
||||
// First state is q0
|
||||
solver.Add(a[m] == q0);
|
||||
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add(x[i] >= 1);
|
||||
solver.Add(x[i] <= S);
|
||||
// Determine a[i+1]: a[i+1] == d2[a[i], x[i]]
|
||||
solver.Add(a[i+1] == d2_flatten.Element(((a[i]*S)+(x[i]-1))));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 3 jugs problem using regular constraint in Google CP Solver.
|
||||
*
|
||||
* A.k.a. water jugs problem.
|
||||
*
|
||||
* Problem from Taha 'Introduction to Operations Research',
|
||||
* page 245f .
|
||||
*
|
||||
* For more info about the problem, see:
|
||||
* http://mathworld.wolfram.com/ThreeJugProblem.html
|
||||
*
|
||||
* This model use a regular constraint for handling the
|
||||
* transitions between the states. Instead of minimizing
|
||||
* the cost in a cost matrix (as shortest path problem),
|
||||
* we here call the model with increasing length of the
|
||||
* sequence array (x).
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/3_jugs_regular.py
|
||||
*
|
||||
*/
|
||||
private static bool Solve(int n)
|
||||
{
|
||||
Solver solver = new Solver("ThreeJugProblem");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
|
||||
// the DFA (for regular)
|
||||
int n_states = 14;
|
||||
int input_max = 15;
|
||||
int initial_state = 1; // state 0 is for the failing state
|
||||
int[] accepting_states = {15};
|
||||
|
||||
//
|
||||
// Manually crafted DFA
|
||||
// (from the adjacency matrix used in the other models)
|
||||
//
|
||||
/*
|
||||
int[,] transition_fn = {
|
||||
// 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||
{0, 2, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 1
|
||||
{0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 2
|
||||
{0, 0, 0, 4, 0, 0, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 3
|
||||
{0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, // 4
|
||||
{0, 0, 0, 0, 0, 6, 0, 0, 9, 0, 0, 0, 0, 0, 0}, // 5
|
||||
{0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0}, // 6
|
||||
{0, 0, 0, 0, 0, 0, 0, 8, 9, 0, 0, 0, 0, 0, 0}, // 7
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, // 8
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0}, // 9
|
||||
{0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0}, // 10
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0}, // 11
|
||||
{0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0}, // 12
|
||||
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0}, // 13
|
||||
{0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 15}, // 14
|
||||
// 15
|
||||
};
|
||||
*/
|
||||
|
||||
//
|
||||
// However, the DFA is easy to create from adjacency lists.
|
||||
//
|
||||
int[][] states = {
|
||||
new int[] {2,9}, // state 1
|
||||
new int[] {3}, // state 2
|
||||
new int[] {4, 9}, // state 3
|
||||
new int[] {5}, // state 4
|
||||
new int[] {6,9}, // state 5
|
||||
new int[] {7}, // state 6
|
||||
new int[] {8,9}, // state 7
|
||||
new int[] {15}, // state 8
|
||||
new int[] {10}, // state 9
|
||||
new int[] {11}, // state 10
|
||||
new int[] {12}, // state 11
|
||||
new int[] {13}, // state 12
|
||||
new int[] {14}, // state 13
|
||||
new int[] {15} // state 14
|
||||
};
|
||||
|
||||
int[,] transition_fn = new int[n_states,input_max];
|
||||
for(int i = 0; i < n_states; i++) {
|
||||
for(int j = 1; j <= input_max; j++) {
|
||||
bool in_states = false;
|
||||
for(int s = 0; s < states[i].Length; s++) {
|
||||
if (j == states[i][s]) {
|
||||
in_states = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (in_states) {
|
||||
transition_fn[i,j-1] = j;
|
||||
} else {
|
||||
transition_fn[i,j-1] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// The name of the nodes, for printing
|
||||
// the solution.
|
||||
//
|
||||
string[] nodes = {
|
||||
"8,0,0", // 1 start
|
||||
"5,0,3", // 2
|
||||
"5,3,0", // 3
|
||||
"2,3,3", // 4
|
||||
"2,5,1", // 5
|
||||
"7,0,1", // 6
|
||||
"7,1,0", // 7
|
||||
"4,1,3", // 8
|
||||
"3,5,0", // 9
|
||||
"3,2,3", // 10
|
||||
"6,2,0", // 11
|
||||
"6,0,2", // 12
|
||||
"1,5,2", // 13
|
||||
"1,4,3", // 14
|
||||
"4,4,0" // 15 goal
|
||||
};
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
// Note: We use 1..2 (instead of 0..1) and subtract 1 in the solution
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 1, input_max, "x");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
MyRegular(solver, x, n_states, input_max, transition_fn,
|
||||
initial_state, accepting_states);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
bool found = false;
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("\nFound a solution of length {0}", n+1);
|
||||
int[] x_val = new int[n];
|
||||
x_val[0] = 1;
|
||||
Console.WriteLine("{0} -> {1}", nodes[0], nodes[x_val[0]]);
|
||||
for(int i = 1; i < n; i++) {
|
||||
// Note: here we subtract 1 to get 0..1
|
||||
int val = (int)x[i].Value()-1;
|
||||
x_val[i] = val;
|
||||
Console.WriteLine("{0} -> {1}", nodes[x_val[i-1]], nodes[x_val[i]]);
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
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());
|
||||
|
||||
found = true;
|
||||
|
||||
}
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
return found;
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
|
||||
for(int n = 1; n < 15; n++) {
|
||||
bool found = Solve(n);
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
201
examples/dotnet/csharp/TaskScheduling.cs
Normal file
201
examples/dotnet/csharp/TaskScheduling.cs
Normal file
@@ -0,0 +1,201 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
namespace OrToolsConstraint {
|
||||
class Job {
|
||||
public Job(List<Task> tasks) {
|
||||
AlternativeTasks = tasks;
|
||||
}
|
||||
public Job Successor { get; set; }
|
||||
public List<Task> AlternativeTasks { get; set; }
|
||||
}
|
||||
|
||||
class Task {
|
||||
public Task(string name, long duration, long equipment) {
|
||||
Name = name;
|
||||
Duration = duration;
|
||||
Equipment = equipment;
|
||||
}
|
||||
|
||||
public string Name {get; set;}
|
||||
public long StartTime {get; set;}
|
||||
public long EndTime {
|
||||
get {
|
||||
return StartTime + Duration;
|
||||
}
|
||||
}
|
||||
public long Duration {get; set;}
|
||||
public long Equipment { get; set; }
|
||||
|
||||
public override string ToString() {
|
||||
return Name + " [ " + Equipment + " ]\tstarts: " + StartTime + " ends:" +
|
||||
EndTime + ", duration: " + Duration;
|
||||
}
|
||||
}
|
||||
|
||||
class Prefix : VoidToString
|
||||
{
|
||||
public override string Run()
|
||||
{
|
||||
return "[TaskScheduling] ";
|
||||
}
|
||||
}
|
||||
|
||||
class TaskScheduling {
|
||||
public static List<Job> myJobList = new List<Job>();
|
||||
public static Dictionary<long, List<IntervalVar>> tasksToEquipment =
|
||||
new Dictionary<long, List<IntervalVar>>();
|
||||
public static Dictionary<string, long> taskIndexes =
|
||||
new Dictionary<string, long>();
|
||||
|
||||
public static void InitTaskList() {
|
||||
List<Task> taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job1Task0a", 15, 0));
|
||||
taskList.Add(new Task("Job1Task0b", 25, 1));
|
||||
taskList.Add(new Task("Job1Task0c", 10, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job1Task1a", 25, 0));
|
||||
taskList.Add(new Task("Job1Task1b", 30, 1));
|
||||
taskList.Add(new Task("Job1Task1c", 40, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job1Task2a", 20, 0));
|
||||
taskList.Add(new Task("Job1Task2b", 35, 1));
|
||||
taskList.Add(new Task("Job1Task2c", 10, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job2Task0a", 15, 0));
|
||||
taskList.Add(new Task("Job2Task0b", 25, 1));
|
||||
taskList.Add(new Task("Job2Task0c", 10, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job2Task1a", 25, 0));
|
||||
taskList.Add(new Task("Job2Task1b", 30, 1));
|
||||
taskList.Add(new Task("Job2Task1c", 40, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job2Task2a", 20, 0));
|
||||
taskList.Add(new Task("Job2Task2b", 35, 1));
|
||||
taskList.Add(new Task("Job2Task2c", 10, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job3Task0a", 10, 0));
|
||||
taskList.Add(new Task("Job3Task0b", 15, 1));
|
||||
taskList.Add(new Task("Job3Task0c", 50, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job3Task1a", 50, 0));
|
||||
taskList.Add(new Task("Job3Task1b", 10, 1));
|
||||
taskList.Add(new Task("Job3Task1c", 20, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task("Job3Task2a", 65, 0));
|
||||
taskList.Add(new Task("Job3Task2b", 5, 1));
|
||||
taskList.Add(new Task("Job3Task2c", 15, 2));
|
||||
myJobList.Add(new Job(taskList));
|
||||
|
||||
myJobList[0].Successor = myJobList[1];
|
||||
myJobList[1].Successor = myJobList[2];
|
||||
myJobList[2].Successor = null;
|
||||
|
||||
myJobList[3].Successor = myJobList[4];
|
||||
myJobList[4].Successor = myJobList[5];
|
||||
myJobList[5].Successor = null;
|
||||
|
||||
myJobList[6].Successor = myJobList[7];
|
||||
myJobList[7].Successor = myJobList[8];
|
||||
myJobList[8].Successor = null;
|
||||
}
|
||||
|
||||
public static int GetTaskCount() {
|
||||
int c = 0;
|
||||
foreach (Job j in myJobList)
|
||||
foreach (Task t in j.AlternativeTasks) {
|
||||
taskIndexes[t.Name] = c;
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
public static int GetEndTaskCount() {
|
||||
int c = 0;
|
||||
foreach (Job j in myJobList)
|
||||
if (j.Successor == null)
|
||||
c += j.AlternativeTasks.Count;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void Main(string[] args) {
|
||||
InitTaskList();
|
||||
int taskCount = GetTaskCount();
|
||||
|
||||
Solver solver = new Solver("ResourceConstraintScheduling");
|
||||
|
||||
IntervalVar[] tasks = new IntervalVar[taskCount];
|
||||
IntVar[] taskChoosed = new IntVar[taskCount];
|
||||
IntVar[] makeSpan = new IntVar[GetEndTaskCount()];
|
||||
|
||||
int endJobCounter = 0;
|
||||
foreach (Job j in myJobList) {
|
||||
IntVar[] tmp = new IntVar[j.AlternativeTasks.Count];
|
||||
int i = 0;
|
||||
foreach (Task t in j.AlternativeTasks) {
|
||||
long ti = taskIndexes[t.Name];
|
||||
taskChoosed[ti] = solver.MakeIntVar(0, 1, t.Name + "_choose");
|
||||
tmp[i++] = taskChoosed[ti];
|
||||
tasks[ti] = solver.MakeFixedDurationIntervalVar(
|
||||
0, 100000, t.Duration, false, t.Name + "_interval");
|
||||
if (j.Successor == null)
|
||||
makeSpan[endJobCounter++] = tasks[ti].EndExpr().Var();
|
||||
if (!tasksToEquipment.ContainsKey(t.Equipment))
|
||||
tasksToEquipment[t.Equipment] = new List<IntervalVar>();
|
||||
tasksToEquipment[t.Equipment].Add(tasks[ti]);
|
||||
}
|
||||
solver.Add(IntVarArrayHelper.Sum(tmp) == 1);
|
||||
}
|
||||
|
||||
List<SequenceVar> all_seq = new List<SequenceVar>();
|
||||
foreach (KeyValuePair<long, List<IntervalVar>> pair in tasksToEquipment) {
|
||||
DisjunctiveConstraint dc = solver.MakeDisjunctiveConstraint(
|
||||
pair.Value.ToArray(), pair.Key.ToString());
|
||||
solver.Add(dc);
|
||||
all_seq.Add(dc.SequenceVar());
|
||||
}
|
||||
|
||||
IntVar objective_var = solver.MakeMax(makeSpan).Var();
|
||||
OptimizeVar objective_monitor = solver.MakeMinimize(objective_var, 1);
|
||||
|
||||
DecisionBuilder sequence_phase =
|
||||
solver.MakePhase(all_seq.ToArray(), Solver.SEQUENCE_DEFAULT);
|
||||
DecisionBuilder objective_phase =
|
||||
solver.MakePhase(objective_var, Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
DecisionBuilder main_phase = solver.Compose(sequence_phase, objective_phase);
|
||||
|
||||
const int kLogFrequency = 1000000;
|
||||
VoidToString prefix = new Prefix();
|
||||
SearchMonitor search_log =
|
||||
solver.MakeSearchLog(kLogFrequency, objective_monitor, prefix);
|
||||
|
||||
SolutionCollector collector = solver.MakeLastSolutionCollector();
|
||||
collector.Add(all_seq.ToArray());
|
||||
collector.AddObjective(objective_var);
|
||||
|
||||
if (solver.Solve(main_phase, search_log, objective_monitor, null, collector))
|
||||
Console.Out.WriteLine("Optimal solution = " + collector.ObjectiveValue(0));
|
||||
else
|
||||
Console.Out.WriteLine("No solution.");
|
||||
}
|
||||
}
|
||||
}
|
||||
263
examples/dotnet/csharp/a_puzzle.cs
Normal file
263
examples/dotnet/csharp/a_puzzle.cs
Normal file
@@ -0,0 +1,263 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class APuzzle
|
||||
{
|
||||
/**
|
||||
*
|
||||
* From "God plays dice"
|
||||
* "A puzzle"
|
||||
* http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/
|
||||
* And the sequel "Answer to a puzzle"
|
||||
* http://gottwurfelt.wordpress.com/2012/02/24/an-answer-to-a-puzzle/
|
||||
*
|
||||
* This problem instance was taken from the latter blog post.
|
||||
* (Problem 1)
|
||||
*
|
||||
* """
|
||||
* 8809 = 6
|
||||
* 7111 = 0
|
||||
* 2172 = 0
|
||||
* 6666 = 4
|
||||
* 1111 = 0
|
||||
* 3213 = 0
|
||||
* 7662 = 2
|
||||
* 9312 = 1
|
||||
* 0000 = 4
|
||||
* 2222 = 0
|
||||
* 3333 = 0
|
||||
* 5555 = 0
|
||||
* 8193 = 3
|
||||
* 8096 = 5
|
||||
* 7777 = 0
|
||||
* 9999 = 4
|
||||
* 7756 = 1
|
||||
* 6855 = 3
|
||||
* 9881 = 5
|
||||
* 5531 = 0
|
||||
*
|
||||
* 2581 = ?
|
||||
* """
|
||||
*
|
||||
* Note:
|
||||
* This model yields 10 solutions, since x4 is not
|
||||
* restricted in the constraints.
|
||||
* All solutions has x assigned to the correct result.
|
||||
*
|
||||
*
|
||||
* (Problem 2)
|
||||
* The problem stated in "A puzzle"
|
||||
* http://gottwurfelt.wordpress.com/2012/02/22/a-puzzle/
|
||||
* is
|
||||
* """
|
||||
* 8809 = 6
|
||||
* 7662 = 2
|
||||
* 9312 = 1
|
||||
* 8193 = 3
|
||||
* 8096 = 5
|
||||
* 7756 = 1
|
||||
* 6855 = 3
|
||||
* 9881 = 5
|
||||
*
|
||||
* 2581 = ?
|
||||
* """
|
||||
* This problem instance yields two different solutions of x,
|
||||
* one is the same (correct) as for the above problem instance,
|
||||
* and one is not.
|
||||
* This is because here x0,x1,x4 and x9 are underdefined.
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static void Solve(int p = 1)
|
||||
{
|
||||
Solver solver = new Solver("APuzzle");
|
||||
|
||||
Console.WriteLine("\nSolving p{0}", p);
|
||||
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 10;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar x0 = solver.MakeIntVar(0, n-1, "x0");
|
||||
IntVar x1 = solver.MakeIntVar(0, n-1, "x1");
|
||||
IntVar x2 = solver.MakeIntVar(0, n-1, "x2");
|
||||
IntVar x3 = solver.MakeIntVar(0, n-1, "x3");
|
||||
IntVar x4 = solver.MakeIntVar(0, n-1, "x4");
|
||||
IntVar x5 = solver.MakeIntVar(0, n-1, "x5");
|
||||
IntVar x6 = solver.MakeIntVar(0, n-1, "x6");
|
||||
IntVar x7 = solver.MakeIntVar(0, n-1, "x7");
|
||||
IntVar x8 = solver.MakeIntVar(0, n-1, "x8");
|
||||
IntVar x9 = solver.MakeIntVar(0, n-1, "x9");
|
||||
|
||||
IntVar[] all = {x0,x1,x2,x3,x4,x5,x6,x7,x8,x9};
|
||||
|
||||
// The unknown, i.e. 2581 = x
|
||||
IntVar x = solver.MakeIntVar(0, n-1, "x");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// Both problem are here shown in two
|
||||
// approaches:
|
||||
// - using equations
|
||||
// - using a a matrix and Sum of each row
|
||||
|
||||
if (p == 1) {
|
||||
|
||||
// Problem 1
|
||||
solver.Add(x8+x8+x0+x9 == 6);
|
||||
solver.Add(x7+x1+x1+x1 == 0);
|
||||
solver.Add(x2+x1+x7+x2 == 0);
|
||||
solver.Add(x6+x6+x6+x6 == 4);
|
||||
solver.Add(x1+x1+x1+x1 == 0);
|
||||
solver.Add(x3+x2+x1+x3 == 0);
|
||||
solver.Add(x7+x6+x6+x2 == 2);
|
||||
solver.Add(x9+x3+x1+x2 == 1);
|
||||
solver.Add(x0+x0+x0+x0 == 4);
|
||||
solver.Add(x2+x2+x2+x2 == 0);
|
||||
solver.Add(x3+x3+x3+x3 == 0);
|
||||
solver.Add(x5+x5+x5+x5 == 0);
|
||||
solver.Add(x8+x1+x9+x3 == 3);
|
||||
solver.Add(x8+x0+x9+x6 == 5);
|
||||
solver.Add(x7+x7+x7+x7 == 0);
|
||||
solver.Add(x9+x9+x9+x9 == 4);
|
||||
solver.Add(x7+x7+x5+x6 == 1);
|
||||
solver.Add(x6+x8+x5+x5 == 3);
|
||||
solver.Add(x9+x8+x8+x1 == 5);
|
||||
solver.Add(x5+x5+x3+x1 == 0);
|
||||
|
||||
// The unknown
|
||||
solver.Add(x2+x5+x8+x1 == x);
|
||||
|
||||
} else if (p == 2) {
|
||||
|
||||
// Another representation of Problem 1
|
||||
int[,] problem1 = {
|
||||
{8,8,0,9, 6},
|
||||
{7,1,1,1, 0},
|
||||
{2,1,7,2, 0},
|
||||
{6,6,6,6, 4},
|
||||
{1,1,1,1, 0},
|
||||
{3,2,1,3, 0},
|
||||
{7,6,6,2, 2},
|
||||
{9,3,1,2, 1},
|
||||
{0,0,0,0, 4},
|
||||
{2,2,2,2, 0},
|
||||
{3,3,3,3, 0},
|
||||
{5,5,5,5, 0},
|
||||
{8,1,9,3, 3},
|
||||
{8,0,9,6, 5},
|
||||
{7,7,7,7, 0},
|
||||
{9,9,9,9, 4},
|
||||
{7,7,5,6, 1},
|
||||
{6,8,5,5, 3},
|
||||
{9,8,8,1, 5},
|
||||
{5,5,3,1, 0}
|
||||
};
|
||||
|
||||
for(int i = 0; i < problem1.GetLength(0); i++) {
|
||||
solver.Add( (from j in Enumerable.Range(0, 4)
|
||||
select all[problem1[i,j]]
|
||||
).ToArray().Sum() == problem1[i,4] );
|
||||
}
|
||||
|
||||
solver.Add(all[2]+all[5]+all[8]+all[1] == x);
|
||||
|
||||
} else if (p == 3) {
|
||||
|
||||
// Problem 2
|
||||
solver.Add(x8+x8+x0+x9 == 6);
|
||||
solver.Add(x7+x6+x6+x2 == 2);
|
||||
solver.Add(x9+x3+x1+x2 == 1);
|
||||
solver.Add(x8+x1+x9+x3 == 3);
|
||||
solver.Add(x8+x0+x9+x6 == 5);
|
||||
solver.Add(x7+x7+x5+x6 == 1);
|
||||
solver.Add(x6+x8+x5+x5 == 3);
|
||||
solver.Add(x9+x8+x8+x1 == 5);
|
||||
|
||||
// The unknown
|
||||
solver.Add(x2+x5+x8+x1 == x);
|
||||
|
||||
} else {
|
||||
|
||||
// Another representation of Problem 2
|
||||
int[,] problem2 = {
|
||||
{8,8,0,9, 6},
|
||||
{7,6,6,2, 2},
|
||||
{9,3,1,2, 1},
|
||||
{8,1,9,3, 3},
|
||||
{8,0,9,6, 5},
|
||||
{7,7,5,6, 1},
|
||||
{6,8,5,5, 3},
|
||||
{9,8,8,1, 5}
|
||||
};
|
||||
|
||||
for(int i = 0; i < problem2.GetLength(0); i++) {
|
||||
solver.Add( (from j in Enumerable.Range(0, 4)
|
||||
select all[problem2[i,j]]
|
||||
).ToArray().Sum() == problem2[i,4] );
|
||||
}
|
||||
|
||||
|
||||
solver.Add(all[2]+all[5]+all[8]+all[1] == x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
int c = 0;
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("x: {0} x0..x9: ", x.Value());
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(all[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
for(int p = 1; p <= 4; p++) {
|
||||
Solve(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
183
examples/dotnet/csharp/a_round_of_golf.cs
Normal file
183
examples/dotnet/csharp/a_round_of_golf.cs
Normal file
@@ -0,0 +1,183 @@
|
||||
//
|
||||
// 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 ARoundOfGolf
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* A Round of Golf puzzle (Dell Logic Puzzles) in Google CP Solver.
|
||||
*
|
||||
* From http://brownbuffalo.sourceforge.net/RoundOfGolfClues.html
|
||||
* """
|
||||
* Title: A Round of Golf
|
||||
* Author: Ellen K. Rodehorst
|
||||
* Publication: Dell Favorite Logic Problems
|
||||
* Issue: Summer, 2000
|
||||
* Puzzle #: 9
|
||||
* Stars: 1
|
||||
*
|
||||
* When the Sunny Hills Country Club golf course isn't in use by club members,
|
||||
* of course, it's open to the club's employees. Recently, Jack and three other
|
||||
* workers at the golf course got together on their day off to play a round of
|
||||
* eighteen holes of golf.
|
||||
* Afterward, all four, including Mr. Green, went to the clubhouse to total
|
||||
* their scorecards. Each man works at a different job (one is a short-order
|
||||
* cook), and each shot a different score in the game. No one scored below
|
||||
* 70 or above 85 strokes. From the clues below, can you discover each man's
|
||||
* full name, job and golf score?
|
||||
*
|
||||
* 1. Bill, who is not the maintenance man, plays golf often and had the lowest
|
||||
* score of the foursome.
|
||||
* 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and scored ten
|
||||
* strokes more than the pro-shop clerk.
|
||||
* 3. In some order, Frank and the caddy scored four and seven more strokes than
|
||||
* Mr. Sands.
|
||||
* 4. Mr. Carter thought his score of 78 was one of his better games, even
|
||||
* though Frank's score was lower.
|
||||
* 5. None of the four scored exactly 81 strokes.
|
||||
*
|
||||
* Determine: First Name - Last Name - Job - Score
|
||||
* """
|
||||
*
|
||||
* See http://www.hakank.org/google_or_tools/a_round_of_golf.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("ARoundOfGolf");
|
||||
|
||||
// number of speakers
|
||||
int n = 4;
|
||||
|
||||
int Jack = 0;
|
||||
int Bill = 1;
|
||||
int Paul = 2;
|
||||
int Frank = 3;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] last_name = solver.MakeIntVarArray(n, 0, n-1, "last_name");
|
||||
// IntVar Green = last_name[0]; // not used
|
||||
IntVar Clubb = last_name[1];
|
||||
IntVar Sands = last_name[2];
|
||||
IntVar Carter = last_name[3];
|
||||
|
||||
IntVar[] job = solver.MakeIntVarArray(n, 0, n-1, "job");
|
||||
// IntVar cook = job[0]; // not used
|
||||
IntVar maintenance_man = job[1];
|
||||
IntVar clerk = job[2];
|
||||
IntVar caddy = job[3];
|
||||
|
||||
IntVar[] score = solver.MakeIntVarArray(n, 70, 85, "score");
|
||||
|
||||
// for search
|
||||
IntVar[] all = new IntVar[n*3];
|
||||
for(int i = 0; i < n; i++) {
|
||||
all[i] = last_name[i];
|
||||
all[i+n] = job[i];
|
||||
all[i+2*n] = score[i];
|
||||
}
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(last_name.AllDifferent());
|
||||
solver.Add(job.AllDifferent());
|
||||
solver.Add(score.AllDifferent());
|
||||
|
||||
// 1. Bill, who is not the maintenance man, plays golf often and had
|
||||
// the lowest score of the foursome.
|
||||
solver.Add(maintenance_man != Bill);
|
||||
solver.Add(score[Bill] < score[Jack]);
|
||||
solver.Add(score[Bill] < score[Paul]);
|
||||
solver.Add(score[Bill] < score[Frank]);
|
||||
|
||||
// 2. Mr. Clubb, who isn't Paul, hit several balls into the woods and
|
||||
// scored ten strokes more than the pro-shop clerk.
|
||||
solver.Add(Clubb != Paul);
|
||||
solver.Add(score.Element(Clubb) == score.Element(clerk) + 10);
|
||||
|
||||
// 3. In some order, Frank and the caddy scored four and seven more
|
||||
// strokes than Mr. Sands.
|
||||
solver.Add(caddy != Frank);
|
||||
solver.Add(Sands != Frank);
|
||||
solver.Add(caddy != Sands);
|
||||
|
||||
IntVar b3_a_1 = score.Element(Sands) + 4 == score[Frank];
|
||||
IntVar b3_a_2 = score.Element(caddy) == score.Element(Sands) + 7;
|
||||
IntVar b3_b_1 = score.Element(Sands) + 7 == score[Frank];
|
||||
IntVar b3_b_2 = score.Element(caddy) == score.Element(Sands) + 4;
|
||||
solver.Add( (b3_a_1*b3_a_2) + (b3_b_1*b3_b_2) == 1);
|
||||
|
||||
// 4. Mr. Carter thought his score of 78 was one of his better games,
|
||||
// even though Frank's score was lower.
|
||||
solver.Add(Carter != Frank);
|
||||
solver.Add(score.Element(Carter) == 78);
|
||||
solver.Add(score[Frank] < score.Element(Carter));
|
||||
|
||||
// 5. None of the four scored exactly 81 strokes.
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add(score[i] != 81);
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine(
|
||||
"Last name: " +
|
||||
String.Join(", ", (from i in last_name
|
||||
select i.Value().ToString()).ToArray()));
|
||||
Console.WriteLine(
|
||||
"Job : " +
|
||||
String.Join(", ", (from i in job
|
||||
select i.Value().ToString()).ToArray()));
|
||||
Console.WriteLine(
|
||||
"Score : " +
|
||||
String.Join(", ", (from i in score
|
||||
select i.Value().ToString()).ToArray()));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
100
examples/dotnet/csharp/all_interval.cs
Normal file
100
examples/dotnet/csharp/all_interval.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class AllInterval
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Implements the all interval problem.
|
||||
* See http://www.hakank.org/google_or_tools/all_interval.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n=12)
|
||||
{
|
||||
Solver solver = new Solver("AllInterval");
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, n-1, "x");
|
||||
IntVar[] diffs = solver.MakeIntVarArray(n-1, 1, n-1, "diffs");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
solver.Add(diffs.AllDifferent());
|
||||
|
||||
for(int k = 0; k < n - 1; k++) {
|
||||
// solver.Add(diffs[k] == (x[k + 1] - x[k]).Abs());
|
||||
solver.Add(diffs[k] == (x[k + 1] - x[k].Abs()));
|
||||
}
|
||||
|
||||
|
||||
// symmetry breaking
|
||||
solver.Add(x[0] < x[n - 1]);
|
||||
solver.Add(diffs[0] < diffs[1]);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", x[i].Value());
|
||||
}
|
||||
Console.Write(" diffs: ");
|
||||
for(int i = 0; i < n-1; i++) {
|
||||
Console.Write("{0} ", diffs[i].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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 = 12;
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(n);
|
||||
}
|
||||
}
|
||||
103
examples/dotnet/csharp/alldifferent_except_0.cs
Normal file
103
examples/dotnet/csharp/alldifferent_except_0.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class AllDifferentExcept0Test
|
||||
{
|
||||
|
||||
//
|
||||
// Decomposition of alldifferent_except_0
|
||||
//
|
||||
public static void AllDifferentExcept0(Solver solver, IntVar[] a) {
|
||||
|
||||
int n = a.Length;
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < i; j++) {
|
||||
solver.Add((a[i] != 0) * (a[j] != 0) <= (a[i] != a[j]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Decomposition of alldifferent_except_0
|
||||
*
|
||||
* See http://www.hakank.org/google_or_tools/map.py
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("AllDifferentExcept0");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int n = 6;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, n - 1 , "x");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
AllDifferentExcept0(solver, x);
|
||||
|
||||
// we also require at least 2 0's
|
||||
IntVar[] z_tmp = new IntVar[n];
|
||||
for(int i = 0; i < n; i++) {
|
||||
z_tmp[i] = x[i] == 0;
|
||||
}
|
||||
IntVar z = z_tmp.Sum().VarWithName("z");
|
||||
solver.Add(z == 2);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("z: {0} x: ", z.Value());
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", x[i].Value());
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
137
examples/dotnet/csharp/assignment.cs
Normal file
137
examples/dotnet/csharp/assignment.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
//
|
||||
// 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 Assignment
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Assignment problem
|
||||
*
|
||||
* From Wayne Winston "Operations Research",
|
||||
* Assignment Problems, page 393f
|
||||
* (generalized version with added test column)
|
||||
*
|
||||
* See See http://www.hakank.org/or-tools/assignment.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Assignment");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
|
||||
// Problem instance
|
||||
// hakank: I added the fifth column to make it more
|
||||
// interesting
|
||||
int rows = 4;
|
||||
int cols = 5;
|
||||
int[,] cost = {
|
||||
{14, 5, 8, 7, 15},
|
||||
{ 2, 12, 6, 5, 3},
|
||||
{ 7, 8, 3, 9, 7},
|
||||
{ 2, 4, 6, 10, 1}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeBoolVarMatrix(rows, cols, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// Exacly one assignment per row (task),
|
||||
// i.e. all rows must be assigned with one worker
|
||||
for(int i = 0; i < rows; i++) {
|
||||
solver.Add((from j in Enumerable.Range(0, cols)
|
||||
select x[i,j]).ToArray().Sum() == 1);
|
||||
}
|
||||
|
||||
// At most one assignments per column (worker)
|
||||
for(int j = 0; j < cols; j++) {
|
||||
solver.Add((from i in Enumerable.Range(0, rows)
|
||||
select x[i,j]).ToArray().Sum() <= 1);
|
||||
}
|
||||
|
||||
// Total cost
|
||||
IntVar total_cost = (from i in Enumerable.Range(0, rows)
|
||||
from j in Enumerable.Range(0, cols)
|
||||
select (cost[i,j] * x[i,j])).ToArray().Sum().Var();
|
||||
|
||||
//
|
||||
// objective
|
||||
//
|
||||
OptimizeVar objective = total_cost.Minimize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db, objective);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("total_cost: {0}", total_cost.Value());
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
Console.Write(x[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Assignments:");
|
||||
for(int i = 0; i < rows; i++) {
|
||||
Console.Write("Task " + i);
|
||||
for(int j = 0; j < cols; j++) {
|
||||
if (x[i,j].Value() == 1) {
|
||||
Console.WriteLine(" is done by " + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
167
examples/dotnet/csharp/broken_weights.cs
Normal file
167
examples/dotnet/csharp/broken_weights.cs
Normal file
@@ -0,0 +1,167 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class BrokenWeights
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Broken weights problem.
|
||||
*
|
||||
* From http://www.mathlesstraveled.com/?p=701
|
||||
* """
|
||||
* Here's a fantastic problem I recently heard. Apparently it was first
|
||||
* posed by Claude Gaspard Bachet de Meziriac in a book of arithmetic problems
|
||||
* published in 1612, and can also be found in Heinrich Dorrie's 100
|
||||
* Great Problems of Elementary Mathematics.
|
||||
*
|
||||
* A merchant had a forty pound measuring weight that broke
|
||||
* into four pieces as the result of a fall. When the pieces were
|
||||
* subsequently weighed, it was found that the weight of each piece
|
||||
* was a whole number of pounds and that the four pieces could be
|
||||
* used to weigh every integral weight between 1 and 40 pounds. What
|
||||
* were the weights of the pieces?
|
||||
*
|
||||
* Note that since this was a 17th-century merchant, he of course used a
|
||||
* balance scale to weigh things. So, for example, he could use a 1-pound
|
||||
* weight and a 4-pound weight to weigh a 3-pound object, by placing the
|
||||
* 3-pound object and 1-pound weight on one side of the scale, and
|
||||
* the 4-pound weight on the other side.
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/broken_weights.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int m=40, int n=4)
|
||||
{
|
||||
Solver solver = new Solver("BrokenWeights");
|
||||
|
||||
Console.WriteLine("Total weight (m): {0}", m);
|
||||
Console.WriteLine("Number of pieces (n): {0}", n);
|
||||
Console.WriteLine();
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
IntVar[] weights = solver.MakeIntVarArray(n, 1, m , "weights");
|
||||
IntVar[,] x = new IntVar[m, n];
|
||||
// Note: in x_flat we insert the weights array before x
|
||||
IntVar[] x_flat = new IntVar[m*n + n];
|
||||
for(int j = 0; j < n; j++) {
|
||||
x_flat[j] = weights[j];
|
||||
}
|
||||
for(int i = 0; i < m; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
x[i,j] = solver.MakeIntVar(-1, 1, "x["+i+","+j+"]");
|
||||
x_flat[n+i*n+j] = x[i,j];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
|
||||
// symmetry breaking
|
||||
for(int j = 1; j < n; j++) {
|
||||
solver.Add(weights[j-1] < weights[j]);
|
||||
}
|
||||
|
||||
|
||||
solver.Add(weights.Sum() == m);
|
||||
|
||||
// Check that all weights from 1 to n (default 40) can be made.
|
||||
//
|
||||
// Since all weights can be on either side
|
||||
// of the side of the scale we allow either
|
||||
// -1, 0, or 1 of the weights, assuming that
|
||||
// -1 is the weights on the left and 1 is on the right.
|
||||
//
|
||||
for(int i = 0; i < m; i++) {
|
||||
solver.Add( (from j in Enumerable.Range(0, n)
|
||||
select weights[j] * x[i,j]).ToArray().Sum() == i+1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// The objective is to minimize the last weight.
|
||||
//
|
||||
OptimizeVar obj = weights[n-1].Minimize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("weights: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0,3} ", weights[i].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
for(int i = 0; i < 10+n*4; i++) {
|
||||
Console.Write("-");
|
||||
}
|
||||
Console.WriteLine();
|
||||
for(int i = 0; i < m; i++) {
|
||||
Console.Write("weight {0,2}:", i+1);
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write("{0,3} ", x[i,j].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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 m = 40;
|
||||
int n = 4;
|
||||
|
||||
if (args.Length > 0) {
|
||||
m = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (args.Length > 1) {
|
||||
n = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
Solve(m, n);
|
||||
}
|
||||
}
|
||||
131
examples/dotnet/csharp/bus_schedule.cs
Normal file
131
examples/dotnet/csharp/bus_schedule.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// 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 BusSchedule
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Bus scheduling.
|
||||
*
|
||||
* Minimize number of buses in timeslots.
|
||||
*
|
||||
* Problem from Taha "Introduction to Operations Research", page 58.
|
||||
*
|
||||
* This is a slightly more general model than Taha's.
|
||||
*
|
||||
* Also see, http://www.hakank.org/or-tools/bus_schedule.py
|
||||
*
|
||||
*/
|
||||
private static long Solve(long num_buses_check = 0)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("BusSchedule");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int time_slots = 6;
|
||||
int[] demands = {8, 10, 7, 12, 4, 4};
|
||||
int max_num = demands.Sum();
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
// How many buses start the schedule at time slot t
|
||||
IntVar[] x = solver.MakeIntVarArray(time_slots, 0, max_num, "x");
|
||||
// Total number of buses
|
||||
IntVar num_buses = x.Sum().VarWithName("num_buses");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// Meet the demands for this and the next time slot.
|
||||
for(int i = 0; i < time_slots - 1; i++) {
|
||||
solver.Add(x[i]+x[i+1] >= demands[i]);
|
||||
}
|
||||
|
||||
// The demand "around the clock"
|
||||
solver.Add(x[time_slots-1] + x[0] - demands[time_slots-1] == 0);
|
||||
|
||||
// For showing all solutions of minimal number of buses
|
||||
if (num_buses_check > 0) {
|
||||
solver.Add(num_buses == num_buses_check);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
if (num_buses_check == 0) {
|
||||
|
||||
// Minimize num_buses
|
||||
OptimizeVar obj = num_buses.Minimize(1);
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
} else {
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
}
|
||||
|
||||
long result = 0;
|
||||
while (solver.NextSolution()) {
|
||||
result = num_buses.Value();
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < time_slots; i++) {
|
||||
Console.Write("{0,2} ", x[i].Value());
|
||||
}
|
||||
Console.WriteLine("num_buses: " + num_buses.Value());
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
|
||||
Console.WriteLine("Check for minimum number of buses: ");
|
||||
long num_buses = Solve();
|
||||
Console.WriteLine("\n... got {0} as minimal value.", num_buses);
|
||||
Console.WriteLine("\nAll solutions: ", num_buses);
|
||||
num_buses = Solve(num_buses);
|
||||
|
||||
}
|
||||
}
|
||||
118
examples/dotnet/csharp/circuit.cs
Normal file
118
examples/dotnet/csharp/circuit.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class CircuitTest
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* circuit(solver, x)
|
||||
*
|
||||
* A decomposition of the global constraint circuit, based
|
||||
* on some observation of the orbits in an array.
|
||||
*
|
||||
* Note: The domain of x must be 0..n-1 (not 1..n)
|
||||
* since C# is 0-based.
|
||||
*/
|
||||
public static void circuit(Solver solver, IntVar[] x) {
|
||||
|
||||
int n = x.Length;
|
||||
IntVar[] z = solver.MakeIntVarArray(n, 0, n - 1, "z");
|
||||
|
||||
solver.Add(x.AllDifferent());
|
||||
solver.Add(z.AllDifferent());
|
||||
|
||||
// put the orbit of x[0] in z[0..n-1]
|
||||
solver.Add(z[0] == x[0]);
|
||||
for(int i = 1; i < n-1; i++) {
|
||||
solver.Add(z[i] == x.Element(z[i-1]));
|
||||
}
|
||||
|
||||
// z may not be 0 for i < n-1
|
||||
for(int i = 1; i < n - 1; i++) {
|
||||
solver.Add(z[i] != 0);
|
||||
}
|
||||
|
||||
// when i = n-1 it must be 0
|
||||
solver.Add(z[n - 1] == 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Implements a (decomposition) of the global constraint circuit.
|
||||
* See http://www.hakank.org/google_or_tools/circuit.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n = 5)
|
||||
{
|
||||
Solver solver = new Solver("Circuit");
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, n-1, "x");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
circuit(solver, x);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", x[i].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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 = 5;
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(n);
|
||||
}
|
||||
}
|
||||
129
examples/dotnet/csharp/circuit2.cs
Normal file
129
examples/dotnet/csharp/circuit2.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class CircuitTest2
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* circuit(solver, x, z)
|
||||
*
|
||||
* A decomposition of the global constraint circuit, based
|
||||
* on some observation of the orbits in an array.
|
||||
*
|
||||
* This version also exposes z (the path) to the public.
|
||||
*
|
||||
* Note: The domain of x must be 0..n-1 (not 1..n)
|
||||
* since C# is 0-based.
|
||||
*/
|
||||
public static void circuit(Solver solver, IntVar[] x, IntVar[] z) {
|
||||
|
||||
int n = x.Length;
|
||||
|
||||
solver.Add(x.AllDifferent());
|
||||
solver.Add(z.AllDifferent());
|
||||
|
||||
// put the orbit of x[0] in z[0..n-1]
|
||||
solver.Add(z[0] == x[0]);
|
||||
for(int i = 1; i < n-1; i++) {
|
||||
solver.Add(z[i] == x.Element(z[i-1]));
|
||||
}
|
||||
|
||||
// z may not be 0 for i < n-1
|
||||
for(int i = 1; i < n - 1; i++) {
|
||||
solver.Add(z[i] != 0);
|
||||
}
|
||||
|
||||
// when i = n-1 it must be 0
|
||||
solver.Add(z[n - 1] == 0);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Implements a (decomposition) of the global constraint circuit
|
||||
* and extracting the path.
|
||||
*
|
||||
* One circuit for n = 5 is 3 0 4 2 1
|
||||
* Thus the extracted path is 0 -> 3 -> 2 -> 4 -> 1 -> 0
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n = 5)
|
||||
{
|
||||
Solver solver = new Solver("CircuitTest2");
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, n-1, "x");
|
||||
IntVar[] path = solver.MakeIntVarArray(n, 0, n-1, "path");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
circuit(solver, x, path);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("x : ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", x[i].Value());
|
||||
}
|
||||
Console.Write("\npath: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", path[i].Value());
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
}
|
||||
|
||||
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 = 5;
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(n);
|
||||
}
|
||||
}
|
||||
404
examples/dotnet/csharp/code_samples_sat.cs
Normal file
404
examples/dotnet/csharp/code_samples_sat.cs
Normal file
@@ -0,0 +1,404 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Sat;
|
||||
|
||||
public class VarArraySolutionPrinter : CpSolverSolutionCallback
|
||||
{
|
||||
public VarArraySolutionPrinter(IntVar[] variables)
|
||||
{
|
||||
variables_ = variables;
|
||||
}
|
||||
|
||||
public override void OnSolutionCallback()
|
||||
{
|
||||
{
|
||||
Console.WriteLine(String.Format("Solution #{0}: time = {1:F2} s",
|
||||
solution_count_, WallTime()));
|
||||
foreach (IntVar v in variables_)
|
||||
{
|
||||
Console.WriteLine(
|
||||
String.Format(" {0} = {1}", v.ShortString(), Value(v)));
|
||||
}
|
||||
solution_count_++;
|
||||
}
|
||||
}
|
||||
|
||||
public int SolutionCount()
|
||||
{
|
||||
return solution_count_;
|
||||
}
|
||||
|
||||
private int solution_count_;
|
||||
private IntVar[] variables_;
|
||||
}
|
||||
|
||||
public class VarArraySolutionPrinterWithObjective : CpSolverSolutionCallback
|
||||
{
|
||||
public VarArraySolutionPrinterWithObjective(IntVar[] variables)
|
||||
{
|
||||
variables_ = variables;
|
||||
}
|
||||
|
||||
public override void OnSolutionCallback()
|
||||
{
|
||||
{
|
||||
Console.WriteLine(String.Format("Solution #{0}: time = {1:F2} s",
|
||||
solution_count_, WallTime()));
|
||||
Console.WriteLine(
|
||||
String.Format(" objective value = {0}", ObjectiveValue()));
|
||||
foreach (IntVar v in variables_)
|
||||
{
|
||||
Console.WriteLine(
|
||||
String.Format(" {0} = {1}", v.ShortString(), Value(v)));
|
||||
}
|
||||
solution_count_++;
|
||||
}
|
||||
}
|
||||
|
||||
public int SolutionCount()
|
||||
{
|
||||
return solution_count_;
|
||||
}
|
||||
|
||||
private int solution_count_;
|
||||
private IntVar[] variables_;
|
||||
}
|
||||
|
||||
|
||||
public class CodeSamplesSat
|
||||
{
|
||||
static void CodeSample()
|
||||
{
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
// Creates the Boolean variable.
|
||||
IntVar x = model.NewBoolVar("x");
|
||||
}
|
||||
|
||||
static void LiteralSample()
|
||||
{
|
||||
CpModel model = new CpModel();
|
||||
IntVar x = model.NewBoolVar("x");
|
||||
ILiteral not_x = x.Not();
|
||||
}
|
||||
|
||||
static void BoolOrSample()
|
||||
{
|
||||
CpModel model = new CpModel();
|
||||
IntVar x = model.NewBoolVar("x");
|
||||
IntVar y = model.NewBoolVar("y");
|
||||
model.AddBoolOr(new ILiteral[] {x, y.Not()});
|
||||
}
|
||||
|
||||
static void ReifiedSample()
|
||||
{
|
||||
CpModel model = new CpModel();
|
||||
|
||||
IntVar x = model.NewBoolVar("x");
|
||||
IntVar y = model.NewBoolVar("y");
|
||||
IntVar b = model.NewBoolVar("b");
|
||||
|
||||
// First version using a half-reified bool and.
|
||||
model.AddBoolAnd(new ILiteral[] {x, y.Not()}).OnlyEnforceIf(b);
|
||||
|
||||
// Second version using implications.
|
||||
model.AddImplication(b, x);
|
||||
model.AddImplication(b, y.Not());
|
||||
|
||||
// Third version using bool or.
|
||||
model.AddBoolOr(new ILiteral[] {b.Not(), x});
|
||||
model.AddBoolOr(new ILiteral[] {b.Not(), y.Not()});
|
||||
}
|
||||
|
||||
static void RabbitsAndPheasants()
|
||||
{
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
// Creates the variables.
|
||||
IntVar r = model.NewIntVar(0, 100, "r");
|
||||
IntVar p = model.NewIntVar(0, 100, "p");
|
||||
// 20 heads.
|
||||
model.Add(r + p == 20);
|
||||
// 56 legs.
|
||||
model.Add(4 * r + 2 * p == 56);
|
||||
|
||||
// Creates a solver and solves the model.
|
||||
CpSolver solver = new CpSolver();
|
||||
CpSolverStatus status = solver.Solve(model);
|
||||
|
||||
if (status == CpSolverStatus.Feasible)
|
||||
{
|
||||
Console.WriteLine(solver.Value(r) + " rabbits, and " +
|
||||
solver.Value(p) + " pheasants");
|
||||
}
|
||||
}
|
||||
|
||||
static void BinpackingProblem()
|
||||
{
|
||||
// Data.
|
||||
int bin_capacity = 100;
|
||||
int slack_capacity = 20;
|
||||
int num_bins = 10;
|
||||
|
||||
int[,] items = new int[,] { {20, 12}, {15, 12}, {30, 8}, {45, 5} };
|
||||
int num_items = items.GetLength(0);
|
||||
|
||||
// Model.
|
||||
CpModel model = new CpModel();
|
||||
|
||||
// Main variables.
|
||||
IntVar[,] x = new IntVar[num_items, num_bins];
|
||||
for (int i = 0; i < num_items; ++i)
|
||||
{
|
||||
int num_copies = items[i, 1];
|
||||
for (int b = 0; b < num_bins; ++b)
|
||||
{
|
||||
x[i, b] = model.NewIntVar(0, num_copies, String.Format("x_{0}_{1}", i, b));
|
||||
}
|
||||
}
|
||||
|
||||
// Load variables.
|
||||
IntVar[] load = new IntVar[num_bins];
|
||||
for (int b = 0; b < num_bins; ++b)
|
||||
{
|
||||
load[b] = model.NewIntVar(0, bin_capacity, String.Format("load_{0}", b));
|
||||
}
|
||||
|
||||
// Slack variables.
|
||||
IntVar[] slacks = new IntVar[num_bins];
|
||||
for (int b = 0; b < num_bins; ++b)
|
||||
{
|
||||
slacks[b] = model.NewBoolVar(String.Format("slack_{0}", b));
|
||||
}
|
||||
|
||||
// Links load and x.
|
||||
int[] sizes = new int[num_items];
|
||||
for (int i = 0; i < num_items; ++i) {
|
||||
sizes[i] = items[i, 0];
|
||||
}
|
||||
for (int b = 0; b < num_bins; ++b)
|
||||
{
|
||||
IntVar[] tmp = new IntVar[num_items];
|
||||
for (int i = 0; i < num_items; ++i)
|
||||
{
|
||||
tmp[i] = x[i, b];
|
||||
}
|
||||
model.Add(load[b] == tmp.ScalProd(sizes));
|
||||
}
|
||||
|
||||
// Place all items.
|
||||
for (int i = 0; i < num_items; ++i)
|
||||
{
|
||||
IntVar[] tmp = new IntVar[num_bins];
|
||||
for (int b = 0; b < num_bins; ++b)
|
||||
{
|
||||
tmp[b] = x[i, b];
|
||||
}
|
||||
model.Add(tmp.Sum() == items[i, 1]);
|
||||
}
|
||||
|
||||
// Links load and slack.
|
||||
int safe_capacity = bin_capacity - slack_capacity;
|
||||
for (int b = 0; b < num_bins; ++b)
|
||||
{
|
||||
// slack[b] => load[b] <= safe_capacity.
|
||||
model.Add(load[b] <= safe_capacity).OnlyEnforceIf(slacks[b]);
|
||||
// not(slack[b]) => load[b] > safe_capacity.
|
||||
model.Add(load[b] > safe_capacity).OnlyEnforceIf(slacks[b].Not());
|
||||
}
|
||||
|
||||
// Maximize sum of slacks.
|
||||
model.Maximize(slacks.Sum());
|
||||
|
||||
// Solves and prints out the solution.
|
||||
CpSolver solver = new CpSolver();
|
||||
CpSolverStatus status = solver.Solve(model);
|
||||
Console.WriteLine(String.Format("Solve status: {0}", status));
|
||||
if (status == CpSolverStatus.Optimal) {
|
||||
Console.WriteLine(String.Format("Optimal objective value: {0}",
|
||||
solver.ObjectiveValue));
|
||||
for (int b = 0; b < num_bins; ++b)
|
||||
{
|
||||
Console.WriteLine(String.Format("load_{0} = {1}",
|
||||
b, solver.Value(load[b])));
|
||||
for (int i = 0; i < num_items; ++i)
|
||||
{
|
||||
Console.WriteLine(string.Format(" item_{0}_{1} = {2}",
|
||||
i, b, solver.Value(x[i, b])));
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine("Statistics");
|
||||
Console.WriteLine(
|
||||
String.Format(" - conflicts : {0}", solver.NumConflicts()));
|
||||
Console.WriteLine(
|
||||
String.Format(" - branches : {0}", solver.NumBranches()));
|
||||
Console.WriteLine(
|
||||
String.Format(" - wall time : {0} s", solver.WallTime()));
|
||||
}
|
||||
|
||||
static void IntervalSample()
|
||||
{
|
||||
CpModel model = new CpModel();
|
||||
int horizon = 100;
|
||||
IntVar start_var = model.NewIntVar(0, horizon, "start");
|
||||
// C# code supports IntVar or integer constants in intervals.
|
||||
int duration = 10;
|
||||
IntVar end_var = model.NewIntVar(0, horizon, "end");
|
||||
IntervalVar interval =
|
||||
model.NewIntervalVar(start_var, duration, end_var, "interval");
|
||||
}
|
||||
|
||||
static void OptionalIntervalSample()
|
||||
{
|
||||
CpModel model = new CpModel();
|
||||
int horizon = 100;
|
||||
IntVar start_var = model.NewIntVar(0, horizon, "start");
|
||||
// C# code supports IntVar or integer constants in intervals.
|
||||
int duration = 10;
|
||||
IntVar end_var = model.NewIntVar(0, horizon, "end");
|
||||
IntVar presence_var = model.NewBoolVar("presence");
|
||||
IntervalVar interval = model.NewOptionalIntervalVar(
|
||||
start_var, duration, end_var, presence_var, "interval");
|
||||
}
|
||||
|
||||
static void MinimalCpSat()
|
||||
{
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
// Creates the variables.
|
||||
int num_vals = 3;
|
||||
|
||||
IntVar x = model.NewIntVar(0, num_vals - 1, "x");
|
||||
IntVar y = model.NewIntVar(0, num_vals - 1, "y");
|
||||
IntVar z = model.NewIntVar(0, num_vals - 1, "z");
|
||||
// Creates the constraints.
|
||||
model.Add(x != y);
|
||||
|
||||
// Creates a solver and solves the model.
|
||||
CpSolver solver = new CpSolver();
|
||||
CpSolverStatus status = solver.Solve(model);
|
||||
|
||||
if (status == CpSolverStatus.Feasible)
|
||||
{
|
||||
Console.WriteLine("x = " + solver.Value(x));
|
||||
Console.WriteLine("y = " + solver.Value(y));
|
||||
Console.WriteLine("z = " + solver.Value(z));
|
||||
}
|
||||
}
|
||||
|
||||
static void MinimalCpSatWithTimeLimit()
|
||||
{
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
// Creates the variables.
|
||||
int num_vals = 3;
|
||||
|
||||
IntVar x = model.NewIntVar(0, num_vals - 1, "x");
|
||||
IntVar y = model.NewIntVar(0, num_vals - 1, "y");
|
||||
IntVar z = model.NewIntVar(0, num_vals - 1, "z");
|
||||
// Creates the constraints.
|
||||
model.Add(x != y);
|
||||
|
||||
// Creates a solver and solves the model.
|
||||
CpSolver solver = new CpSolver();
|
||||
|
||||
// Adds a time limit. Parameters are stored as strings in the solver.
|
||||
solver.StringParameters = "max_time_in_seconds:10.0" ;
|
||||
|
||||
CpSolverStatus status = solver.Solve(model);
|
||||
|
||||
if (status == CpSolverStatus.Feasible)
|
||||
{
|
||||
Console.WriteLine("x = " + solver.Value(x));
|
||||
Console.WriteLine("y = " + solver.Value(y));
|
||||
Console.WriteLine("z = " + solver.Value(z));
|
||||
}
|
||||
}
|
||||
|
||||
static void MinimalCpSatPrintIntermediateSolutions()
|
||||
{
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
// Creates the variables.
|
||||
int num_vals = 3;
|
||||
|
||||
IntVar x = model.NewIntVar(0, num_vals - 1, "x");
|
||||
IntVar y = model.NewIntVar(0, num_vals - 1, "y");
|
||||
IntVar z = model.NewIntVar(0, num_vals - 1, "z");
|
||||
// Creates the constraints.
|
||||
model.Add(x != y);
|
||||
// Create the objective.
|
||||
model.Maximize(x + 2 * y + 3 * z);
|
||||
|
||||
// Creates a solver and solves the model.
|
||||
CpSolver solver = new CpSolver();
|
||||
VarArraySolutionPrinterWithObjective cb =
|
||||
new VarArraySolutionPrinterWithObjective(new IntVar[] {x, y, z});
|
||||
solver.SearchAllSolutions(model, cb);
|
||||
Console.WriteLine(String.Format("Number of solutions found: {0}",
|
||||
cb.SolutionCount()));
|
||||
}
|
||||
|
||||
static void MinimalCpSatAllSolutions()
|
||||
{
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
// Creates the variables.
|
||||
int num_vals = 3;
|
||||
|
||||
IntVar x = model.NewIntVar(0, num_vals - 1, "x");
|
||||
IntVar y = model.NewIntVar(0, num_vals - 1, "y");
|
||||
IntVar z = model.NewIntVar(0, num_vals - 1, "z");
|
||||
// Creates the constraints.
|
||||
model.Add(x != y);
|
||||
|
||||
// Creates a solver and solves the model.
|
||||
CpSolver solver = new CpSolver();
|
||||
VarArraySolutionPrinter cb =
|
||||
new VarArraySolutionPrinter(new IntVar[] {x, y, z});
|
||||
solver.SearchAllSolutions(model, cb);
|
||||
Console.WriteLine(String.Format("Number of solutions found: {0}",
|
||||
cb.SolutionCount()));
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
Console.WriteLine("--- CodeSample ---");
|
||||
CodeSample();
|
||||
Console.WriteLine("--- LiteralSample ---");
|
||||
LiteralSample();
|
||||
Console.WriteLine("--- BoolOrSample ---");
|
||||
BoolOrSample();
|
||||
Console.WriteLine("--- ReifiedSample ---");
|
||||
ReifiedSample();
|
||||
Console.WriteLine("--- RabbitsAndPheasants ---");
|
||||
RabbitsAndPheasants();
|
||||
Console.WriteLine("--- BinpackingProblem ---");
|
||||
BinpackingProblem();
|
||||
Console.WriteLine("--- IntervalSample ---");
|
||||
IntervalSample();
|
||||
Console.WriteLine("--- OptionalIntervalSample ---");
|
||||
OptionalIntervalSample();
|
||||
Console.WriteLine("--- MinimalCpSat ---");
|
||||
MinimalCpSat();
|
||||
Console.WriteLine("--- MinimalCpSatWithTimeLimit ---");
|
||||
MinimalCpSatWithTimeLimit();
|
||||
Console.WriteLine("--- MinimalCpSatPrintIntermediateSolutions ---");
|
||||
MinimalCpSatPrintIntermediateSolutions();
|
||||
Console.WriteLine("--- MinimalCpSatAllSolutions ---");
|
||||
MinimalCpSatAllSolutions();
|
||||
}
|
||||
}
|
||||
114
examples/dotnet/csharp/coins3.cs
Normal file
114
examples/dotnet/csharp/coins3.cs
Normal file
@@ -0,0 +1,114 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class Coins3
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Coin application.
|
||||
*
|
||||
* From "Constraint Logic Programming using ECLiPSe"
|
||||
* pages 99f and 234 ff.
|
||||
* The solution in ECLiPSe is at page 236.
|
||||
*
|
||||
* """
|
||||
* What is the minimum number of coins that allows one to pay _exactly_
|
||||
* any amount smaller than one Euro? Recall that there are six different
|
||||
* euro cents, of denomination 1, 2, 5, 10, 20, 50
|
||||
* """
|
||||
|
||||
* Also see http://www.hakank.org/or-tools/coins3.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Coins3");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 6; // number of different coins
|
||||
int[] variables = {1, 2, 5, 10, 25, 50};
|
||||
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, 99, "x");
|
||||
IntVar num_coins = x.Sum().VarWithName("num_coins");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// Check that all changes from 1 to 99 can be made.
|
||||
for(int j = 1; j < 100; j++) {
|
||||
IntVar[] tmp = solver.MakeIntVarArray(n, 0, 99, "tmp");
|
||||
solver.Add(tmp.ScalProd(variables) == j);
|
||||
|
||||
foreach(int i in RANGE) {
|
||||
solver.Add(tmp[i] <= x[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = num_coins.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("num_coins: {0}", num_coins.Value());
|
||||
Console.Write("x: ");
|
||||
foreach(int i in RANGE) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
113
examples/dotnet/csharp/coins_grid.cs
Normal file
113
examples/dotnet/csharp/coins_grid.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class CoinsGrid
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves the Coins Grid problm.
|
||||
* See http://www.hakank.org/google_or_tools/coins_grid.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n = 31, int c = 14)
|
||||
{
|
||||
Solver solver = new Solver("CoinsGrid");
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 0, 1 , "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// sum row/columns == c
|
||||
for(int i = 0; i < n; i++) {
|
||||
IntVar[] row = new IntVar[n];
|
||||
IntVar[] col = new IntVar[n];
|
||||
for(int j = 0; j < n; j++) {
|
||||
row[j] = x[i,j];
|
||||
col[j] = x[j,i];
|
||||
}
|
||||
solver.Add(row.Sum() == c);
|
||||
solver.Add(col.Sum() == c);
|
||||
}
|
||||
|
||||
// quadratic horizonal distance
|
||||
IntVar[] obj_tmp = new IntVar[n * n];
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
obj_tmp[i * n + j] = (x[i,j] * (i - j) * (i - j)).Var();
|
||||
}
|
||||
}
|
||||
IntVar obj_var = obj_tmp.Sum().Var();
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = obj_var.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("obj: " + obj_var.Value());
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write(x[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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 = 31;
|
||||
int c = 14;
|
||||
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (args.Length > 1) {
|
||||
c = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
|
||||
Solve(n, c);
|
||||
}
|
||||
}
|
||||
118
examples/dotnet/csharp/combinatorial_auction2.cs
Normal file
118
examples/dotnet/csharp/combinatorial_auction2.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class CombinatorialAuction2
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Combinatorial auction.
|
||||
*
|
||||
* This is a more general model for the combinatorial example
|
||||
* in the Numberjack Tutorial, pages 9 and 24 (slides 19/175 and
|
||||
* 51/175).
|
||||
*
|
||||
* See http://www.hakank.org/or-tools/combinatorial_auction2.py
|
||||
*
|
||||
* The original and more talkative model is here:
|
||||
* http://www.hakank.org/numberjack/combinatorial_auction.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("CombinatorialAuction2");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 5;
|
||||
|
||||
// the items for each bid
|
||||
int[][] items = {
|
||||
new int[] {0,1}, // A,B
|
||||
new int[] {0,2}, // A, C
|
||||
new int[] {1,3}, // B,D
|
||||
new int[] {1,2,3}, // B,C,D
|
||||
new int[] {0} // A
|
||||
};
|
||||
|
||||
int[] bid_ids = {0,1,2,3};
|
||||
int[] bid_amount = {10,20,30,40,14};
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x");
|
||||
IntVar z = x.ScalProd(bid_amount).VarWithName("z");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
foreach(int bid_id in bid_ids) {
|
||||
|
||||
var tmp2 = (from item in Enumerable.Range(0, n)
|
||||
from i in Enumerable.Range(0, items[item].Length)
|
||||
where items[item][i] == bid_id
|
||||
select x[item]);
|
||||
|
||||
solver.Add(tmp2.ToArray().Sum() <= 1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = z.Maximize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("z: {0,2} x: ", z.Value());
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
209
examples/dotnet/csharp/contiguity_regular.cs
Normal file
209
examples/dotnet/csharp/contiguity_regular.cs
Normal file
@@ -0,0 +1,209 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Diagnostics;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class ContiguityRegular
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
* Global constraint regular
|
||||
*
|
||||
* This is a translation of MiniZinc's regular constraint (defined in
|
||||
* lib/zinc/globals.mzn), via the Comet code refered above.
|
||||
* All comments are from the MiniZinc code.
|
||||
* """
|
||||
* The sequence of values in array 'x' (which must all be in the range 1..S)
|
||||
* is accepted by the DFA of 'Q' states with input 1..S and transition
|
||||
* function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'
|
||||
* (which must be in 1..Q) and accepting states 'F' (which all must be in
|
||||
* 1..Q). We reserve state 0 to be an always failing state.
|
||||
* """
|
||||
*
|
||||
* x : IntVar array
|
||||
* Q : number of states
|
||||
* S : input_max
|
||||
* d : transition matrix
|
||||
* q0: initial state
|
||||
* F : accepting states
|
||||
*
|
||||
*/
|
||||
static void MyRegular(Solver solver,
|
||||
IntVar[] x,
|
||||
int Q,
|
||||
int S,
|
||||
int[,] d,
|
||||
int q0,
|
||||
int[] F) {
|
||||
|
||||
|
||||
|
||||
Debug.Assert(Q > 0, "regular: 'Q' must be greater than zero");
|
||||
Debug.Assert(S > 0, "regular: 'S' must be greater than zero");
|
||||
|
||||
// d2 is the same as d, except we add one extra transition for
|
||||
// each possible input; each extra transition is from state zero
|
||||
// to state zero. This allows us to continue even if we hit a
|
||||
// non-accepted input.
|
||||
int[][] d2 = new int[Q+1][];
|
||||
for(int i = 0; i <= Q; i++) {
|
||||
int[] row = new int[S];
|
||||
for(int j = 0; j < S; j++) {
|
||||
if (i == 0) {
|
||||
row[j] = 0;
|
||||
} else {
|
||||
row[j] = d[i-1,j];
|
||||
}
|
||||
}
|
||||
d2[i] = row;
|
||||
}
|
||||
|
||||
int[] d2_flatten = (from i in Enumerable.Range(0, Q+1)
|
||||
from j in Enumerable.Range(0, S)
|
||||
select d2[i][j]).ToArray();
|
||||
|
||||
// If x has index set m..n, then a[m-1] holds the initial state
|
||||
// (q0), and a[i+1] holds the state we're in after processing
|
||||
// x[i]. If a[n] is in F, then we succeed (ie. accept the
|
||||
// string).
|
||||
int m = 0;
|
||||
int n = x.Length;
|
||||
|
||||
IntVar[] a = solver.MakeIntVarArray(n+1-m, 0,Q+1, "a");
|
||||
// Check that the final state is in F
|
||||
solver.Add(a[a.Length-1].Member(F));
|
||||
// First state is q0
|
||||
solver.Add(a[m] == q0);
|
||||
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add(x[i] >= 1);
|
||||
solver.Add(x[i] <= S);
|
||||
// Determine a[i+1]: a[i+1] == d2[a[i], x[i]]
|
||||
solver.Add(a[i+1] == d2_flatten.Element(((a[i]*S)+(x[i]-1))));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void MyContiguity(Solver solver, IntVar[] x) {
|
||||
|
||||
// the DFA (for regular)
|
||||
int n_states = 3;
|
||||
int input_max = 2;
|
||||
int initial_state = 1; // note: state 0 is used for the failing state
|
||||
// in MyRegular
|
||||
|
||||
// all states are accepting states
|
||||
int[] accepting_states = {1,2,3};
|
||||
|
||||
// The regular expression 0*1*0*
|
||||
int[,] transition_fn =
|
||||
{
|
||||
{1,2}, // state 1 (start): input 0 -> state 1, input 1 -> state 2 i.e. 0*
|
||||
{3,2}, // state 2: 1*
|
||||
{3,0}, // state 3: 0*
|
||||
};
|
||||
|
||||
MyRegular(solver, x, n_states, input_max, transition_fn,
|
||||
initial_state, accepting_states);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Global constraint contiguity using regular
|
||||
*
|
||||
* This is a decomposition of the global constraint global contiguity.
|
||||
*
|
||||
* From Global Constraint Catalogue
|
||||
* http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html
|
||||
* """
|
||||
* Enforce all variables of the VARIABLES collection to be assigned to 0 or 1.
|
||||
* In addition, all variables assigned to value 1 appear contiguously.
|
||||
*
|
||||
* Example:
|
||||
* (<0, 1, 1, 0>)
|
||||
*
|
||||
* The global_contiguity constraint holds since the sequence 0 1 1 0 contains
|
||||
* no more than one group of contiguous 1.
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/contiguity_regular.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("ContiguityRegular");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 7; // length of the array
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
// Note: We use 1..2 (instead of 0..1) and subtract 1 in the solution
|
||||
IntVar[] reg_input = solver.MakeIntVarArray(n, 1, 2, "reg_input");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
MyContiguity(solver, reg_input);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(reg_input,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
// Note: here we subtract 1 to get 0..1
|
||||
Console.Write((reg_input[i].Value()-1) + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
123
examples/dotnet/csharp/contiguity_transition.cs
Normal file
123
examples/dotnet/csharp/contiguity_transition.cs
Normal file
@@ -0,0 +1,123 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Diagnostics;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class ContiguityRegular
|
||||
{
|
||||
|
||||
static void MyContiguity(Solver solver, IntVar[] x) {
|
||||
|
||||
// the DFA (for regular)
|
||||
int initial_state = 1;
|
||||
|
||||
// all states are accepting states
|
||||
int[] accepting_states = {1,2,3};
|
||||
|
||||
// The regular expression 0*1*0* {state, input, next state}
|
||||
int[,] transition_tuples = { {1, 0, 1},
|
||||
{1, 1, 2},
|
||||
{2, 0, 3},
|
||||
{2, 1, 2},
|
||||
{3, 0, 3} };
|
||||
|
||||
IntTupleSet result = new IntTupleSet(3);
|
||||
result.InsertAll(transition_tuples);
|
||||
|
||||
solver.Add(x.Transition(result,
|
||||
initial_state,
|
||||
accepting_states));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Global constraint contiguity using Transition
|
||||
*
|
||||
* This version use the built-in TransitionConstraint.
|
||||
*
|
||||
* From Global Constraint Catalogue
|
||||
* http://www.emn.fr/x-info/sdemasse/gccat/Cglobal_contiguity.html
|
||||
* """
|
||||
* Enforce all variables of the VARIABLES collection to be assigned to 0 or 1.
|
||||
* In addition, all variables assigned to value 1 appear contiguously.
|
||||
*
|
||||
* Example:
|
||||
* (<0, 1, 1, 0>)
|
||||
*
|
||||
* The global_contiguity constraint holds since the sequence 0 1 1 0 contains
|
||||
* no more than one group of contiguous 1.
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/contiguity_regular.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("ContiguityRegular");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 7; // length of the array
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
IntVar[] reg_input = solver.MakeIntVarArray(n, 0, 1, "reg_input");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
MyContiguity(solver, reg_input);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(reg_input,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write((reg_input[i].Value()) + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
181
examples/dotnet/csharp/costas_array.cs
Normal file
181
examples/dotnet/csharp/costas_array.cs
Normal file
@@ -0,0 +1,181 @@
|
||||
//
|
||||
// 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 CostasArray
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Costas array
|
||||
*
|
||||
* From http://mathworld.wolfram.com/CostasArray.html:
|
||||
* """
|
||||
* An order-n Costas array is a permutation on {1,...,n} such
|
||||
* that the distances in each row of the triangular difference
|
||||
* table are distinct. For example, the permutation {1,3,4,2,5}
|
||||
* has triangular difference table {2,1,-2,3}, {3,-1,1}, {1,2},
|
||||
* and {4}. Since each row contains no duplications, the permutation
|
||||
* is therefore a Costas array.
|
||||
* """
|
||||
*
|
||||
* Also see
|
||||
* http://en.wikipedia.org/wiki/Costas_array
|
||||
* http://hakank.org/or-tools/costas_array.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n = 6)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("CostasArray");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
Console.WriteLine("n: {0}", n);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] costas = solver.MakeIntVarArray(n, 1, n, "costas");
|
||||
IntVar[,] differences = solver.MakeIntVarMatrix(n, n, -n+1, n-1,
|
||||
"differences");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// Fix the values in the lower triangle in the
|
||||
// difference matrix to -n+1. This removes variants
|
||||
// of the difference matrix for the the same Costas array.
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j <= i; j++ ) {
|
||||
solver.Add(differences[i,j] == -n+1);
|
||||
}
|
||||
}
|
||||
|
||||
// hakank: All the following constraints are from
|
||||
// Barry O'Sullivans's original model.
|
||||
//
|
||||
solver.Add(costas.AllDifferent());
|
||||
|
||||
|
||||
// "How do the positions in the Costas array relate
|
||||
// to the elements of the distance triangle."
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (i < j) {
|
||||
solver.Add( differences[i,j] - (costas[j] - costas[j-i-1]) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// "All entries in a particular row of the difference
|
||||
// triangle must be distint."
|
||||
for(int i = 0; i < n-2; i++) {
|
||||
IntVar[] tmp = (
|
||||
from j in Enumerable.Range(0, n)
|
||||
where j > i
|
||||
select differences[i,j]).ToArray();
|
||||
solver.Add(tmp.AllDifferent());
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// "All the following are redundant - only here to speed up search."
|
||||
//
|
||||
|
||||
// "We can never place a 'token' in the same row as any other."
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (i < j) {
|
||||
solver.Add(differences[i,j] != 0);
|
||||
solver.Add(differences[i,j] != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int k = 2; k < n; k++) {
|
||||
for(int l = 2; l < n; l++) {
|
||||
if (k < l) {
|
||||
solver.Add(
|
||||
(differences[k-2,l-1] + differences[k,l]) -
|
||||
(differences[k-1,l-1] + differences[k-1,l]) == 0
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(costas,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("costas: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", costas[i].Value());
|
||||
}
|
||||
Console.WriteLine("\ndifferences:");
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
long v = differences[i,j].Value();
|
||||
if (v == -n+1) {
|
||||
Console.Write(" ");
|
||||
} else {
|
||||
Console.Write("{0,2} ", v);
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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 = 6;
|
||||
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(n);
|
||||
|
||||
}
|
||||
}
|
||||
128
examples/dotnet/csharp/covering_opl.cs
Normal file
128
examples/dotnet/csharp/covering_opl.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class SetCoveringOPL
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves a set covering problem.
|
||||
* See See http://www.hakank.org/or-tools/set_covering_opl.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("SetCoveringOPL");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int num_workers = 32;
|
||||
int num_tasks = 15;
|
||||
|
||||
// Which worker is qualified for each task.
|
||||
// Note: This is 1-based and will be made 0-base below.
|
||||
int[][] qualified = {
|
||||
new int[] { 1, 9, 19, 22, 25, 28, 31 },
|
||||
new int[] { 2, 12, 15, 19, 21, 23, 27, 29, 30, 31, 32 },
|
||||
new int[] { 3, 10, 19, 24, 26, 30, 32 },
|
||||
new int[] { 4, 21, 25, 28, 32 },
|
||||
new int[] { 5, 11, 16, 22, 23, 27, 31 },
|
||||
new int[] { 6, 20, 24, 26, 30, 32 },
|
||||
new int[] { 7, 12, 17, 25, 30, 31 } ,
|
||||
new int[] { 8, 17, 20, 22, 23 },
|
||||
new int[] { 9, 13, 14, 26, 29, 30, 31 },
|
||||
new int[] { 10, 21, 25, 31, 32 },
|
||||
new int[] { 14, 15, 18, 23, 24, 27, 30, 32 },
|
||||
new int[] { 18, 19, 22, 24, 26, 29, 31 },
|
||||
new int[] { 11, 20, 25, 28, 30, 32 },
|
||||
new int[] { 16, 19, 23, 31 },
|
||||
new int[] { 9, 18, 26, 28, 31, 32 }
|
||||
};
|
||||
|
||||
int[] cost = {1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3,
|
||||
3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 7, 8, 9};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] hire = solver.MakeIntVarArray(num_workers, 0, 1, "workers");
|
||||
IntVar total_cost = hire.ScalProd(cost).Var();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
for(int j = 0; j < num_tasks; j++) {
|
||||
// Sum the cost for hiring the qualified workers
|
||||
// (also, make 0-base).
|
||||
int len = qualified[j].Length;
|
||||
IntVar[] tmp = new IntVar[len];
|
||||
for(int c = 0; c < len; c++) {
|
||||
tmp[c] = hire[qualified[j][c] - 1];
|
||||
}
|
||||
solver.Add(tmp.Sum() >= 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// objective
|
||||
//
|
||||
OptimizeVar objective = total_cost.Minimize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(hire,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, objective);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("Cost: " + total_cost.Value());
|
||||
Console.Write("Hire: ");
|
||||
for(int i = 0; i < num_workers; i++) {
|
||||
if (hire[i].Value() == 1) {
|
||||
Console.Write(i + " ");
|
||||
}
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
272
examples/dotnet/csharp/crew.cs
Normal file
272
examples/dotnet/csharp/crew.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
//
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
188
examples/dotnet/csharp/crossword.cs
Normal file
188
examples/dotnet/csharp/crossword.cs
Normal file
@@ -0,0 +1,188 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
// Note: During compilation, there are a couple of
|
||||
// warnings about assigned but never used variables.
|
||||
// It's the characters a..z so it's quite benign.
|
||||
|
||||
|
||||
public class Crossword
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solving a simple crossword.
|
||||
* See http://www.hakank.org/or-tools/crossword2.py
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Crossword");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
String[] alpha = {"_","a","b","c","d","e","f",
|
||||
"g","h","i","j","k","l","m",
|
||||
"n","o","p","q","r","s","t",
|
||||
"u","v","w","x","y","z"};
|
||||
|
||||
int a=1; int b=2; int c=3; int d=4; int e=5; int f=6;
|
||||
int g=7; int h=8; int i=9; int j=10; int k=11; int l=12;
|
||||
int m=13; int n=14; int o=15; int p=16; int q=17; int r=18;
|
||||
int s=19; int t=20; int u=21; int v=22; int w=23; int x=24;
|
||||
int y=25; int z=26;
|
||||
|
||||
const int num_words = 15;
|
||||
int word_len = 5;
|
||||
|
||||
int[,] AA = {{h, o, s, e, s}, // HOSES
|
||||
{l, a, s, e, r}, // LASER
|
||||
{s, a, i, l, s}, // SAILS
|
||||
{s, h, e, e, t}, // SHEET
|
||||
{s, t, e, e, r}, // STEER
|
||||
{h, e, e, l, 0}, // HEEL
|
||||
{h, i, k, e, 0}, // HIKE
|
||||
{k, e, e, l, 0}, // KEEL
|
||||
{k, n, o, t, 0}, // KNOT
|
||||
{l, i, n, e, 0}, // LINE
|
||||
{a, f, t, 0, 0}, // AFT
|
||||
{a, l, e, 0, 0}, // ALE
|
||||
{e, e, l, 0, 0}, // EEL
|
||||
{l, e, e, 0, 0}, // LEE
|
||||
{t, i, e, 0, 0}}; // TIE
|
||||
|
||||
int num_overlapping = 12;
|
||||
int[,] overlapping = {{0, 2, 1, 0}, // s
|
||||
{0, 4, 2, 0}, // s
|
||||
|
||||
{3, 1, 1, 2}, // i
|
||||
{3, 2, 4, 0}, // k
|
||||
{3, 3, 2, 2}, // e
|
||||
|
||||
{6, 0, 1, 3}, // l
|
||||
{6, 1, 4, 1}, // e
|
||||
{6, 2, 2, 3}, // e
|
||||
|
||||
{7, 0, 5, 1}, // l
|
||||
{7, 2, 1, 4}, // s
|
||||
{7, 3, 4, 2}, // e
|
||||
{7, 4, 2, 4}}; // r
|
||||
|
||||
int N = 8;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
// for labeling on A and E
|
||||
IntVar[,] A = solver.MakeIntVarMatrix(num_words, word_len,
|
||||
0, 26, "A");
|
||||
IntVar[] A_flat = A.Flatten();
|
||||
IntVar[] all = new IntVar[(num_words * word_len) + N];
|
||||
for(int I = 0; I < num_words; I++) {
|
||||
for(int J = 0; J < word_len; J++) {
|
||||
all[I * word_len + J] = A[I,J];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
IntVar[] E = solver.MakeIntVarArray(N, 0, num_words, "E");
|
||||
for(int I = 0; I < N; I++) {
|
||||
all[num_words * word_len + I] = E[I];
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(E.AllDifferent());
|
||||
|
||||
for(int I = 0; I < num_words; I++) {
|
||||
for(int J = 0; J < word_len; J++) {
|
||||
solver.Add(A[I,J] == AA[I,J]);
|
||||
}
|
||||
}
|
||||
|
||||
// This contraint handles the overlappings.
|
||||
//
|
||||
// It's coded in MiniZinc as
|
||||
//
|
||||
// forall(i in 1..num_overlapping) (
|
||||
// A[E[overlapping[i,1]], overlapping[i,2]] =
|
||||
// A[E[overlapping[i,3]], overlapping[i,4]]
|
||||
// )
|
||||
// and in or-tools/Python as
|
||||
// solver.Add(
|
||||
// solver.Element(A_flat,E[overlapping[I][0]]*word_len+overlapping[I][1])
|
||||
// ==
|
||||
// solver.Element(A_flat,E[overlapping[I][2]]*word_len+overlapping[I][3]))
|
||||
//
|
||||
for(int I = 0; I < num_overlapping; I++) {
|
||||
solver.Add(
|
||||
A_flat.Element(E[overlapping[I,0]] * word_len + overlapping[I,1]) ==
|
||||
A_flat.Element(E[overlapping[I,2]] * word_len + overlapping[I,3]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("E: ");
|
||||
for(int ee = 0; ee < N; ee++) {
|
||||
int e_val = (int)E[ee].Value();
|
||||
Console.Write(ee + ": (" + e_val + ") ");
|
||||
for(int ii = 0; ii < word_len; ii++) {
|
||||
Console.Write(alpha[(int)A[ee,ii].Value()]);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
119
examples/dotnet/csharp/crypta.cs
Normal file
119
examples/dotnet/csharp/crypta.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Crypta
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Cryptarithmetic puzzle.
|
||||
*
|
||||
* Prolog benchmark problem GNU Prolog (crypta.pl)
|
||||
* """
|
||||
* Name : crypta.pl
|
||||
* Title : crypt-arithmetic
|
||||
* Original Source: P. Van Hentenryck's book
|
||||
* Adapted by : Daniel Diaz - INRIA France
|
||||
* Date : September 1992
|
||||
*
|
||||
* Solve the operation:
|
||||
*
|
||||
* B A I J J A J I I A H F C F E B B J E A
|
||||
* + D H F G A B C D I D B I F F A G F E J E
|
||||
* -----------------------------------------
|
||||
* = G J E G A C D D H F A F J B F I H E E F
|
||||
* """
|
||||
*
|
||||
*
|
||||
* Also see http://hakank.org/or-tools/crypta.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Crypta");
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar A = solver.MakeIntVar(0, 9, "A");
|
||||
IntVar B = solver.MakeIntVar(0, 9, "B");
|
||||
IntVar C = solver.MakeIntVar(0, 9, "C");
|
||||
IntVar D = solver.MakeIntVar(0, 9, "D");
|
||||
IntVar E = solver.MakeIntVar(0, 9, "E");
|
||||
IntVar F = solver.MakeIntVar(0, 9, "F");
|
||||
IntVar G = solver.MakeIntVar(0, 9, "G");
|
||||
IntVar H = solver.MakeIntVar(0, 9, "H");
|
||||
IntVar I = solver.MakeIntVar(0, 9, "I");
|
||||
IntVar J = solver.MakeIntVar(0, 9, "J");
|
||||
|
||||
IntVar[] LD = new IntVar[] {A,B,C,D,E,F,G,H,I,J};
|
||||
|
||||
IntVar Sr1 = solver.MakeIntVar(0, 1, "Sr1");
|
||||
IntVar Sr2 = solver.MakeIntVar(0, 1, "Sr2");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(LD.AllDifferent());
|
||||
solver.Add(B >= 1);
|
||||
solver.Add(D >= 1);
|
||||
solver.Add(G >= 1);
|
||||
|
||||
solver.Add((A+10*E+100*J+1000*B+10000*B+100000*E+1000000*F+
|
||||
E+10*J+100*E+1000*F+10000*G+100000*A+1000000*F) ==
|
||||
(F+10*E+100*E+1000*H+10000*I+100000*F+1000000*B+10000000*Sr1));
|
||||
|
||||
|
||||
solver.Add((C+10*F+100*H+1000*A+10000*I+100000*I+1000000*J+
|
||||
F+10*I+100*B+1000*D+10000*I+100000*D+1000000*C+Sr1) ==
|
||||
(J+10*F+100*A+1000*F+10000*H+100000*D+1000000*D+10000000*Sr2));
|
||||
|
||||
|
||||
solver.Add((A+10*J+100*J+1000*I+10000*A+100000*B+
|
||||
B+10*A+100*G+1000*F+10000*H+100000*D+Sr2) ==
|
||||
(C+10*A+100*G+1000*E+10000*J+100000*G));
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(LD,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < 10; i++) {
|
||||
Console.Write(LD[i].ToString() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
152
examples/dotnet/csharp/crypto.cs
Normal file
152
examples/dotnet/csharp/crypto.cs
Normal file
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Crypto
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Crypto problem.
|
||||
*
|
||||
* This is the standard benchmark "crypto" problem.
|
||||
*
|
||||
* From GLPK:s model cryto.mod.
|
||||
*
|
||||
* """
|
||||
* This problem comes from the newsgroup rec.puzzle.
|
||||
* The numbers from 1 to 26 are assigned to the letters of the alphabet.
|
||||
* The numbers beside each word are the total of the values assigned to
|
||||
* the letters in the word (e.g. for LYRE: L, Y, R, E might be to equal
|
||||
* 5, 9, 20 and 13, or any other combination that add up to 47).
|
||||
* Find the value of each letter under the equations:
|
||||
*
|
||||
* BALLET 45 GLEE 66 POLKA 59 SONG 61
|
||||
* CELLO 43 JAZZ 58 QUARTET 50 SOPRANO 82
|
||||
* CONCERT 74 LYRE 47 SAXOPHONE 134 THEME 72
|
||||
* FLUTE 30 OBOE 53 SCALE 51 VIOLIN 100
|
||||
* FUGUE 50 OPERA 65 SOLO 37 WALTZ 34
|
||||
*
|
||||
* Solution:
|
||||
* A, B,C, D, E,F, G, H, I, J, K,L,M, N, O, P,Q, R, S,T,U, V,W, X, Y, Z
|
||||
* 5,13,9,16,20,4,24,21,25,17,23,2,8,12,10,19,7,11,15,3,1,26,6,22,14,18
|
||||
*
|
||||
* Reference:
|
||||
* Koalog Constraint Solver <http://www.koalog.com/php/jcs.php>,
|
||||
* Simple problems, the crypto-arithmetic puzzle ALPHACIPHER.
|
||||
* """
|
||||
*
|
||||
* Also see http://hakank.org/or-tools/crypto.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Crypto");
|
||||
|
||||
int num_letters = 26;
|
||||
|
||||
int BALLET = 45;
|
||||
int CELLO = 43;
|
||||
int CONCERT = 74;
|
||||
int FLUTE = 30;
|
||||
int FUGUE = 50;
|
||||
int GLEE = 66;
|
||||
int JAZZ = 58;
|
||||
int LYRE = 47;
|
||||
int OBOE = 53;
|
||||
int OPERA = 65;
|
||||
int POLKA = 59;
|
||||
int QUARTET = 50;
|
||||
int SAXOPHONE = 134;
|
||||
int SCALE = 51;
|
||||
int SOLO = 37;
|
||||
int SONG = 61;
|
||||
int SOPRANO = 82;
|
||||
int THEME = 72;
|
||||
int VIOLIN = 100;
|
||||
int WALTZ = 34;
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] LD = solver.MakeIntVarArray(num_letters, 1, num_letters, "LD");
|
||||
|
||||
// Note D is not used in the constraints below
|
||||
IntVar A = LD[0]; IntVar B = LD[1]; IntVar C = LD[2]; // IntVar D = LD[3];
|
||||
IntVar E = LD[4]; IntVar F = LD[5]; IntVar G = LD[6]; IntVar H = LD[7];
|
||||
IntVar I = LD[8]; IntVar J = LD[9]; IntVar K = LD[10]; IntVar L = LD[11];
|
||||
IntVar M = LD[12]; IntVar N = LD[13]; IntVar O = LD[14]; IntVar P = LD[15];
|
||||
IntVar Q = LD[16]; IntVar R = LD[17]; IntVar S = LD[18]; IntVar T = LD[19];
|
||||
IntVar U = LD[20]; IntVar V = LD[21]; IntVar W = LD[22]; IntVar X = LD[23];
|
||||
IntVar Y = LD[24]; IntVar Z = LD[25];
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(LD.AllDifferent());
|
||||
solver.Add( B + A + L + L + E + T == BALLET);
|
||||
solver.Add( C + E + L + L + O == CELLO);
|
||||
solver.Add( C + O + N + C + E + R + T == CONCERT);
|
||||
solver.Add( F + L + U + T + E == FLUTE);
|
||||
solver.Add( F + U + G + U + E == FUGUE);
|
||||
solver.Add( G + L + E + E == GLEE);
|
||||
solver.Add( J + A + Z + Z == JAZZ);
|
||||
solver.Add( L + Y + R + E == LYRE);
|
||||
solver.Add( O + B + O + E == OBOE);
|
||||
solver.Add( O + P + E + R + A == OPERA);
|
||||
solver.Add( P + O + L + K + A == POLKA);
|
||||
solver.Add( Q + U + A + R + T + E + T == QUARTET);
|
||||
solver.Add(S + A + X + O + P + H + O + N + E == SAXOPHONE);
|
||||
solver.Add( S + C + A + L + E == SCALE);
|
||||
solver.Add( S + O + L + O == SOLO);
|
||||
solver.Add( S + O + N + G == SONG);
|
||||
solver.Add( S + O + P + R + A + N + O == SOPRANO);
|
||||
solver.Add( T + H + E + M + E == THEME);
|
||||
solver.Add( V + I + O + L + I + N == VIOLIN);
|
||||
solver.Add( W + A + L + T + Z == WALTZ);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(LD,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < num_letters; i++) {
|
||||
Console.WriteLine("{0}: {1,2}", str[i], LD[i].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
355
examples/dotnet/csharp/cscvrptw.cs
Normal file
355
examples/dotnet/csharp/cscvrptw.cs
Normal file
@@ -0,0 +1,355 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Generic;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
/// <summary>
|
||||
/// Sample showing how to model and solve a capacitated vehicle routing
|
||||
/// problem with time windows using the swig-wrapped version of the vehicle
|
||||
/// routing library in src/constraint_solver.
|
||||
/// </summary>
|
||||
public class CapacitatedVehicleRoutingProblemWithTimeWindows {
|
||||
|
||||
/// <summary>
|
||||
/// A position on the map with (x, y) coordinates.
|
||||
/// </summary>
|
||||
class Position {
|
||||
public Position() {
|
||||
this.x_ = 0;
|
||||
this.y_ = 0;
|
||||
}
|
||||
|
||||
public Position(int x, int y) {
|
||||
this.x_ = x;
|
||||
this.y_ = y;
|
||||
}
|
||||
|
||||
public int x_;
|
||||
public int y_;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A time window with start/end data.
|
||||
/// </summary>
|
||||
class TimeWindow {
|
||||
public TimeWindow() {
|
||||
this.start_ = -1;
|
||||
this.end_ = -1;
|
||||
}
|
||||
|
||||
public TimeWindow(int start, int end) {
|
||||
this.start_ = start;
|
||||
this.end_ = end;
|
||||
}
|
||||
|
||||
public int start_;
|
||||
public int end_;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Manhattan distance implemented as a callback. It uses an array of
|
||||
/// positions and computes the Manhattan distance between the two
|
||||
/// positions of two different indices.
|
||||
/// </summary>
|
||||
class Manhattan : NodeEvaluator2 {
|
||||
public Manhattan(Position[] locations, int coefficient) {
|
||||
this.locations_ = locations;
|
||||
this.coefficient_ = coefficient;
|
||||
}
|
||||
|
||||
public override long Run(int first_index, int second_index) {
|
||||
if (first_index >= locations_.Length ||
|
||||
second_index >= locations_.Length) {
|
||||
return 0;
|
||||
}
|
||||
return (Math.Abs(locations_[first_index].x_ -
|
||||
locations_[second_index].x_) +
|
||||
Math.Abs(locations_[first_index].y_ -
|
||||
locations_[second_index].y_)) * coefficient_;
|
||||
}
|
||||
|
||||
private Position[] locations_;
|
||||
private int coefficient_;
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// A callback that computes the volume of a demand stored in an
|
||||
/// integer array.
|
||||
/// </summary>
|
||||
class Demand : NodeEvaluator2 {
|
||||
public Demand(int[] order_demands) {
|
||||
this.order_demands_ = order_demands;
|
||||
}
|
||||
|
||||
public override long Run(int first_index, int second_index) {
|
||||
if (first_index < order_demands_.Length) {
|
||||
return order_demands_[first_index];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int[] order_demands_;
|
||||
};
|
||||
|
||||
/// Locations representing either an order location or a vehicle route
|
||||
/// start/end.
|
||||
private Position[] locations_;
|
||||
/// Quantity to be picked up for each order.
|
||||
private int[] order_demands_;
|
||||
/// Time window in which each order must be performed.
|
||||
private TimeWindow[] order_time_windows_;
|
||||
/// Penalty cost "paid" for dropping an order.
|
||||
private int[] order_penalties_;
|
||||
/// Capacity of the vehicles.
|
||||
private int vehicle_capacity_ = 0;
|
||||
/// Latest time at which each vehicle must end its tour.
|
||||
private int[] vehicle_end_time_;
|
||||
/// Cost per unit of distance of each vehicle.
|
||||
private int[] vehicle_cost_coefficients_;
|
||||
/// Vehicle start and end indices. They have to be implemented as int[] due
|
||||
/// to the available SWIG-ed interface.
|
||||
private int[] vehicle_starts_;
|
||||
private int[] vehicle_ends_;
|
||||
|
||||
/// Random number generator to produce data.
|
||||
private Random random_generator = new Random(0xBEEF);
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a capacitated vehicle routing problem with time windows.
|
||||
/// </summary>
|
||||
private CapacitatedVehicleRoutingProblemWithTimeWindows() {}
|
||||
|
||||
/// <summary>
|
||||
/// Creates order data. Location of the order is random, as well
|
||||
/// as its demand (quantity), time window and penalty. ///
|
||||
/// </summary>
|
||||
/// <param name="number_of_orders"> number of orders to build. </param>
|
||||
/// <param name="x_max"> maximum x coordinate in which orders are located.
|
||||
/// </param>
|
||||
/// <param name="y_max"> maximum y coordinate in which orders are located.
|
||||
/// </param>
|
||||
/// <param name="demand_max"> maximum quantity of a demand. </param>
|
||||
/// <param name="time_window_max"> maximum starting time of the order time
|
||||
/// window. </param>
|
||||
/// <param name="time_window_width"> duration of the order time window.
|
||||
/// </param>
|
||||
/// <param name="penalty_min"> minimum pernalty cost if order is dropped.
|
||||
/// </param>
|
||||
/// <param name="penalty_max"> maximum pernalty cost if order is dropped.
|
||||
/// </param>
|
||||
private void BuildOrders(int number_of_orders,
|
||||
int number_of_vehicles,
|
||||
int x_max, int y_max,
|
||||
int demand_max,
|
||||
int time_window_max,
|
||||
int time_window_width,
|
||||
int penalty_min,
|
||||
int penalty_max) {
|
||||
Console.WriteLine("Building orders.");
|
||||
locations_ = new Position[number_of_orders + 2 * number_of_vehicles];
|
||||
order_demands_ = new int[number_of_orders];
|
||||
order_time_windows_ = new TimeWindow[number_of_orders];
|
||||
order_penalties_ = new int[number_of_orders];
|
||||
for (int order = 0; order < number_of_orders; ++order) {
|
||||
locations_[order] =
|
||||
new Position(random_generator.Next(x_max + 1),
|
||||
random_generator.Next(y_max + 1));
|
||||
order_demands_[order] = random_generator.Next(demand_max + 1);
|
||||
int time_window_start = random_generator.Next(time_window_max + 1);
|
||||
order_time_windows_[order] =
|
||||
new TimeWindow(time_window_start,
|
||||
time_window_start + time_window_width);
|
||||
order_penalties_[order] =
|
||||
random_generator.Next(penalty_max - penalty_min + 1) + penalty_min;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates fleet data. Vehicle starting and ending locations are
|
||||
/// random, as well as vehicle costs per distance unit.
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="number_of_orders"> number of orders</param>
|
||||
/// <param name="number_of_vehicles"> number of vehicles</param>
|
||||
/// <param name="x_max"> maximum x coordinate in which orders are located.
|
||||
/// </param>
|
||||
/// <param name="y_max"> maximum y coordinate in which orders are located.
|
||||
/// </param>
|
||||
/// <param name="end_time"> latest end time of a tour of a vehicle. </param>
|
||||
/// <param name="capacity"> capacity of a vehicle. </param>
|
||||
/// <param name="cost_coefficient_max"> maximum cost per distance unit of a
|
||||
/// vehicle (minimum is 1)</param>
|
||||
private void BuildFleet(int number_of_orders,
|
||||
int number_of_vehicles,
|
||||
int x_max, int y_max,
|
||||
int end_time,
|
||||
int capacity,
|
||||
int cost_coefficient_max) {
|
||||
Console.WriteLine("Building fleet.");
|
||||
vehicle_capacity_ = capacity;
|
||||
vehicle_starts_ = new int[number_of_vehicles];
|
||||
vehicle_ends_ = new int[number_of_vehicles];
|
||||
vehicle_end_time_ = new int[number_of_vehicles];
|
||||
vehicle_cost_coefficients_ = new int[number_of_vehicles];
|
||||
for (int vehicle = 0; vehicle < number_of_vehicles; ++vehicle) {
|
||||
int index = 2 * vehicle + number_of_orders;
|
||||
vehicle_starts_[vehicle] = index;
|
||||
locations_[index] =
|
||||
new Position(random_generator.Next(x_max + 1),
|
||||
random_generator.Next(y_max + 1));
|
||||
vehicle_ends_[vehicle] = index + 1;
|
||||
locations_[index + 1] =
|
||||
new Position(random_generator.Next(x_max + 1),
|
||||
random_generator.Next(y_max + 1));
|
||||
vehicle_end_time_[vehicle] = end_time;
|
||||
vehicle_cost_coefficients_[vehicle] =
|
||||
random_generator.Next(cost_coefficient_max) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Solves the current routing problem.
|
||||
/// </summary>
|
||||
private void Solve(int number_of_orders, int number_of_vehicles) {
|
||||
Console.WriteLine("Creating model with " + number_of_orders +
|
||||
" orders and " + number_of_vehicles + " vehicles.");
|
||||
// Finalizing model
|
||||
int number_of_locations = locations_.Length;
|
||||
|
||||
RoutingModel model =
|
||||
new RoutingModel(number_of_locations, number_of_vehicles,
|
||||
vehicle_starts_, vehicle_ends_);
|
||||
|
||||
// Setting up dimensions
|
||||
const int big_number = 100000;
|
||||
NodeEvaluator2 manhattan_callback = new Manhattan(locations_, 1);
|
||||
model.AddDimension(
|
||||
manhattan_callback, big_number, big_number, false, "time");
|
||||
NodeEvaluator2 demand_callback = new Demand(order_demands_);
|
||||
model.AddDimension(demand_callback, 0, vehicle_capacity_, true, "capacity");
|
||||
|
||||
// Setting up vehicles
|
||||
NodeEvaluator2[] cost_callbacks = new NodeEvaluator2[number_of_vehicles];
|
||||
for (int vehicle = 0; vehicle < number_of_vehicles; ++vehicle) {
|
||||
int cost_coefficient = vehicle_cost_coefficients_[vehicle];
|
||||
NodeEvaluator2 manhattan_cost_callback =
|
||||
new Manhattan(locations_, cost_coefficient);
|
||||
cost_callbacks[vehicle] = manhattan_cost_callback;
|
||||
model.SetVehicleCost(vehicle, manhattan_cost_callback);
|
||||
model.CumulVar(model.End(vehicle), "time").SetMax(
|
||||
vehicle_end_time_[vehicle]);
|
||||
}
|
||||
|
||||
// Setting up orders
|
||||
for (int order = 0; order < number_of_orders; ++order) {
|
||||
model.CumulVar(order, "time").SetRange(order_time_windows_[order].start_,
|
||||
order_time_windows_[order].end_);
|
||||
int[] orders = {order};
|
||||
model.AddDisjunction(orders, order_penalties_[order]);
|
||||
}
|
||||
|
||||
// Solving
|
||||
RoutingSearchParameters search_parameters =
|
||||
RoutingModel.DefaultSearchParameters();
|
||||
search_parameters.FirstSolutionStrategy =
|
||||
FirstSolutionStrategy.Types.Value.AllUnperformed;
|
||||
|
||||
Console.WriteLine("Search");
|
||||
Assignment solution = model.SolveWithParameters(search_parameters);
|
||||
|
||||
//protect callbacks from the GC
|
||||
GC.KeepAlive(manhattan_callback);
|
||||
GC.KeepAlive(demand_callback);
|
||||
for (int cost_callback_index = 0; cost_callback_index < cost_callbacks.Length; cost_callback_index++) {
|
||||
GC.KeepAlive(cost_callbacks[cost_callback_index]);
|
||||
}
|
||||
|
||||
if (solution != null) {
|
||||
String output = "Total cost: " + solution.ObjectiveValue() + "\n";
|
||||
// Dropped orders
|
||||
String dropped = "";
|
||||
for (int order = 0; order < number_of_orders; ++order) {
|
||||
if (solution.Value(model.NextVar(order)) == order) {
|
||||
dropped += " " + order;
|
||||
}
|
||||
}
|
||||
if (dropped.Length > 0) {
|
||||
output += "Dropped orders:" + dropped + "\n";
|
||||
}
|
||||
// Routes
|
||||
for (int vehicle = 0; vehicle < number_of_vehicles; ++vehicle) {
|
||||
String route = "Vehicle " + vehicle + ": ";
|
||||
long order = model.Start(vehicle);
|
||||
if (model.IsEnd(solution.Value(model.NextVar(order)))) {
|
||||
route += "Empty";
|
||||
} else {
|
||||
for (;
|
||||
!model.IsEnd(order);
|
||||
order = solution.Value(model.NextVar(order))) {
|
||||
IntVar local_load = model.CumulVar(order, "capacity");
|
||||
IntVar local_time = model.CumulVar(order, "time");
|
||||
route += order + " Load(" + solution.Value(local_load) + ") " +
|
||||
"Time(" + solution.Min(local_time) + ", " +
|
||||
solution.Max(local_time) + ") -> ";
|
||||
}
|
||||
IntVar load = model.CumulVar(order, "capacity");
|
||||
IntVar time = model.CumulVar(order, "time");
|
||||
route += order + " Load(" + solution.Value(load) + ") " +
|
||||
"Time(" + solution.Min(time) + ", " + solution.Max(time) + ")";
|
||||
}
|
||||
output += route + "\n";
|
||||
}
|
||||
Console.WriteLine(output);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
CapacitatedVehicleRoutingProblemWithTimeWindows problem =
|
||||
new CapacitatedVehicleRoutingProblemWithTimeWindows();
|
||||
int x_max = 20;
|
||||
int y_max = 20;
|
||||
int demand_max = 3;
|
||||
int time_window_max = 24 * 60;
|
||||
int time_window_width = 4 * 60;
|
||||
int penalty_min = 50;
|
||||
int penalty_max = 100;
|
||||
int end_time = 24 * 60;
|
||||
int cost_coefficient_max = 3;
|
||||
|
||||
int orders = 100;
|
||||
int vehicles = 20;
|
||||
int capacity = 50;
|
||||
|
||||
problem.BuildOrders(orders,
|
||||
vehicles,
|
||||
x_max,
|
||||
y_max,
|
||||
demand_max,
|
||||
time_window_max,
|
||||
time_window_width,
|
||||
penalty_min,
|
||||
penalty_max);
|
||||
problem.BuildFleet(orders,
|
||||
vehicles,
|
||||
x_max,
|
||||
y_max,
|
||||
end_time,
|
||||
capacity,
|
||||
cost_coefficient_max);
|
||||
problem.Solve(orders, vehicles);
|
||||
}
|
||||
}
|
||||
108
examples/dotnet/csharp/csflow.cs
Normal file
108
examples/dotnet/csharp/csflow.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Graph;
|
||||
|
||||
public class CsFlow
|
||||
{
|
||||
private static void SolveMaxFlow()
|
||||
{
|
||||
Console.WriteLine("Max Flow Problem");
|
||||
int numNodes = 6;
|
||||
int numArcs = 9;
|
||||
int[] tails = {0, 0, 0, 0, 1, 2, 3, 3, 4};
|
||||
int[] heads = {1, 2, 3, 4, 3, 4, 4, 5, 5};
|
||||
int[] capacities = {5, 8, 5, 3, 4, 5, 6, 6, 4};
|
||||
int[] expectedFlows = {4, 4, 2, 0, 4, 4, 0, 6, 4};
|
||||
int expectedTotalFlow = 10;
|
||||
MaxFlow maxFlow = new MaxFlow();
|
||||
for (int i = 0; i < numArcs; ++i)
|
||||
{
|
||||
int arc = maxFlow.AddArcWithCapacity(tails[i], heads[i], capacities[i]);
|
||||
if (arc != i) throw new Exception("Internal error");
|
||||
}
|
||||
int source = 0;
|
||||
int sink = numNodes - 1;
|
||||
Console.WriteLine("Solving max flow with " + numNodes + " nodes, and " +
|
||||
numArcs + " arcs, source=" + source + ", sink=" + sink);
|
||||
int solveStatus = maxFlow.Solve(source, sink);
|
||||
if (solveStatus == MaxFlow.OPTIMAL)
|
||||
{
|
||||
long totalFlow = maxFlow.OptimalFlow();
|
||||
Console.WriteLine("total computed flow " + totalFlow +
|
||||
", expected = " + expectedTotalFlow);
|
||||
for (int i = 0; i < numArcs; ++i)
|
||||
{
|
||||
Console.WriteLine("Arc " + i + " (" + maxFlow.Head(i) + " -> " +
|
||||
maxFlow.Tail(i) + "), capacity = " +
|
||||
maxFlow.Capacity(i) + ") computed = " +
|
||||
maxFlow.Flow(i) + ", expected = " + expectedFlows[i]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Solving the max flow problem failed. Solver status: " +
|
||||
solveStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private static void SolveMinCostFlow()
|
||||
{
|
||||
Console.WriteLine("Min Cost Flow Problem");
|
||||
int numSources = 4;
|
||||
int numTargets = 4;
|
||||
int[,] costs = { {90, 75, 75, 80},
|
||||
{35, 85, 55, 65},
|
||||
{125, 95, 90, 105},
|
||||
{45, 110, 95, 115} };
|
||||
int expectedCost = 275;
|
||||
MinCostFlow minCostFlow = new MinCostFlow();
|
||||
for (int source = 0; source < numSources; ++source)
|
||||
{
|
||||
for (int target = 0; target < numTargets; ++target) {
|
||||
minCostFlow.AddArcWithCapacityAndUnitCost(
|
||||
source, /*target=*/numSources + target, /*capacity=*/1,
|
||||
/*flow unit cost=*/costs[source, target]);
|
||||
}
|
||||
}
|
||||
for (int source = 0; source < numSources; ++source)
|
||||
{
|
||||
minCostFlow.SetNodeSupply(source, 1);
|
||||
}
|
||||
for (int target = 0; target < numTargets; ++target)
|
||||
{
|
||||
minCostFlow.SetNodeSupply(numSources + target, -1);
|
||||
}
|
||||
Console.WriteLine("Solving min cost flow with " + numSources +
|
||||
" sources, and " + numTargets + " targets.");
|
||||
int solveStatus = minCostFlow.Solve();
|
||||
if (solveStatus == MinCostFlow.OPTIMAL)
|
||||
{
|
||||
Console.WriteLine("total computed flow cost = " +
|
||||
minCostFlow.OptimalCost() +
|
||||
", expected = " + expectedCost);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine("Solving the min cost flow problem failed." +
|
||||
" Solver status: " + solveStatus);
|
||||
}
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
SolveMaxFlow();
|
||||
SolveMinCostFlow();
|
||||
}
|
||||
}
|
||||
95
examples/dotnet/csharp/csfz.cs
Normal file
95
examples/dotnet/csharp/csfz.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Flatzinc;
|
||||
|
||||
public class CsFz
|
||||
{
|
||||
/**
|
||||
* Loads a flatzinc file (passed as the first argument) and solves it.
|
||||
*/
|
||||
private static void Solve(String filename)
|
||||
{
|
||||
Model model = new Model(filename);
|
||||
model.LoadFromFile(filename);
|
||||
// Uncomment to see the model.
|
||||
// Console.WriteLine(model.ToString());
|
||||
// This is mandatory.
|
||||
model.PresolveForCp(/*verbose=*/false);
|
||||
// Display basic statistics on the model.
|
||||
model.PrintStatistics();
|
||||
|
||||
FlatzincParameters parameters = new FlatzincParameters();
|
||||
// Initialize to default values as in the C++ runner.
|
||||
parameters.all_solutions = false;
|
||||
parameters.free_search = false;
|
||||
parameters.last_conflict = false;
|
||||
parameters.heuristic_period = 100;
|
||||
parameters.ignore_unknown = false;
|
||||
parameters.log_period = 10000000;
|
||||
parameters.luby_restart = -1;
|
||||
parameters.num_solutions = 0;
|
||||
parameters.restart_log_size = -1;
|
||||
parameters.threads = 0;
|
||||
parameters.time_limit_in_ms = 10000;
|
||||
parameters.logging = false;
|
||||
parameters.verbose_impact = false;
|
||||
parameters.thread_id = -1;
|
||||
parameters.search_type = FlatzincParameters.DEFAULT;
|
||||
// Mandatory to retrieve solutions.
|
||||
parameters.store_all_solutions = true;
|
||||
|
||||
Solver solver = new Solver(model);
|
||||
solver.Solve(parameters);
|
||||
|
||||
int last = solver.NumStoredSolutions() - 1;
|
||||
if (last >= 0) {
|
||||
SolutionOutputSpecsVector output_vector = model.output();
|
||||
foreach (SolutionOutputSpecs output in output_vector) {
|
||||
if (output.variable != null) {
|
||||
IntegerVariable var = output.variable;
|
||||
Console.WriteLine(output.name + " = " +
|
||||
solver.StoredValue(last, var));
|
||||
}
|
||||
if (output.flat_variables.Count > 0) {
|
||||
String line = output.name;
|
||||
foreach (SolutionOutputSpecs.Bounds b in output.bounds) {
|
||||
line += "[" + b.ToString() + "]";
|
||||
}
|
||||
line += " = {";
|
||||
bool start = true;
|
||||
foreach (IntegerVariable var in output.flat_variables) {
|
||||
if (start) {
|
||||
start = false;
|
||||
} else {
|
||||
line += ", ";
|
||||
}
|
||||
line += solver.StoredValue(last, var);
|
||||
}
|
||||
line += "}";
|
||||
Console.WriteLine(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
if (args.Length == 0) {
|
||||
Console.WriteLine("A file name is required!");
|
||||
} else {
|
||||
Solve(args[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
124
examples/dotnet/csharp/csintegerprogramming.cs
Normal file
124
examples/dotnet/csharp/csintegerprogramming.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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 CsIntegerProgramming
|
||||
{
|
||||
private static void RunIntegerProgrammingExample(String solverType)
|
||||
{
|
||||
Solver solver = Solver.CreateSolver("IntegerProgramming", solverType);
|
||||
if (solver == null)
|
||||
{
|
||||
Console.WriteLine("Could not create solver " + solverType);
|
||||
return;
|
||||
}
|
||||
// x1 and x2 are integer non-negative variables.
|
||||
Variable x1 = solver.MakeIntVar(0.0, double.PositiveInfinity, "x1");
|
||||
Variable x2 = solver.MakeIntVar(0.0, double.PositiveInfinity, "x2");
|
||||
|
||||
// Minimize x1 + 2 * x2.
|
||||
Objective objective = solver.Objective();
|
||||
objective.SetMinimization();
|
||||
objective.SetCoefficient(x1, 1);
|
||||
objective.SetCoefficient(x2, 2);
|
||||
|
||||
// 2 * x2 + 3 * x1 >= 17.
|
||||
Constraint ct = solver.MakeConstraint(17, double.PositiveInfinity);
|
||||
ct.SetCoefficient(x1, 3);
|
||||
ct.SetCoefficient(x2, 2);
|
||||
|
||||
int resultStatus = solver.Solve();
|
||||
|
||||
// Check that the problem has an optimal solution.
|
||||
if (resultStatus != Solver.OPTIMAL)
|
||||
{
|
||||
Console.WriteLine("The problem does not have an optimal solution!");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Problem solved in " + solver.WallTime() +
|
||||
" milliseconds");
|
||||
|
||||
// The objective value of the solution.
|
||||
Console.WriteLine("Optimal objective value = " + objective.Value());
|
||||
|
||||
// The value of each variable in the solution.
|
||||
Console.WriteLine("x1 = " + x1.SolutionValue());
|
||||
Console.WriteLine("x2 = " + x2.SolutionValue());
|
||||
|
||||
Console.WriteLine("Advanced usage:");
|
||||
Console.WriteLine("Problem solved in " + solver.Nodes() +
|
||||
" branch-and-bound nodes");
|
||||
}
|
||||
|
||||
private static void RunIntegerProgrammingExampleNaturalApi(String solverType)
|
||||
{
|
||||
Solver solver = Solver.CreateSolver("IntegerProgramming", solverType);
|
||||
if (solver == null)
|
||||
{
|
||||
Console.WriteLine("Could not create solver " + solverType);
|
||||
return;
|
||||
}
|
||||
// x1 and x2 are integer non-negative variables.
|
||||
Variable x1 = solver.MakeIntVar(0.0, double.PositiveInfinity, "x1");
|
||||
Variable x2 = solver.MakeIntVar(0.0, double.PositiveInfinity, "x2");
|
||||
|
||||
solver.Minimize(x1 + 2 * x2);
|
||||
solver.Add(2 * x2 + 3 * x1 >= 17);
|
||||
|
||||
int resultStatus = solver.Solve();
|
||||
|
||||
// Check that the problem has an optimal solution.
|
||||
if (resultStatus != Solver.OPTIMAL)
|
||||
{
|
||||
Console.WriteLine("The problem does not have an optimal solution!");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Problem solved in " + solver.WallTime() +
|
||||
" milliseconds");
|
||||
|
||||
// The objective value of the solution.
|
||||
Console.WriteLine("Optimal objective value = " +
|
||||
solver.Objective().Value());
|
||||
|
||||
// The value of each variable in the solution.
|
||||
Console.WriteLine("x1 = " + x1.SolutionValue());
|
||||
Console.WriteLine("x2 = " + x2.SolutionValue());
|
||||
|
||||
Console.WriteLine("Advanced usage:");
|
||||
Console.WriteLine("Problem solved in " + solver.Nodes() +
|
||||
" branch-and-bound nodes");
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
Console.WriteLine("---- Integer programming example with GLPK ----");
|
||||
RunIntegerProgrammingExample("GLPK_MIXED_INTEGER_PROGRAMMING");
|
||||
Console.WriteLine("---- Linear programming example with CBC ----");
|
||||
RunIntegerProgrammingExample("CBC_MIXED_INTEGER_PROGRAMMING");
|
||||
Console.WriteLine("---- Linear programming example with SCIP ----");
|
||||
RunIntegerProgrammingExample("SCIP_MIXED_INTEGER_PROGRAMMING");
|
||||
Console.WriteLine(
|
||||
"---- Integer programming example (Natural API) with GLPK ----");
|
||||
RunIntegerProgrammingExampleNaturalApi("GLPK_MIXED_INTEGER_PROGRAMMING");
|
||||
Console.WriteLine(
|
||||
"---- Linear programming example (Natural API) with CBC ----");
|
||||
RunIntegerProgrammingExampleNaturalApi("CBC_MIXED_INTEGER_PROGRAMMING");
|
||||
Console.WriteLine(
|
||||
"---- Linear programming example (Natural API) with SCIP ----");
|
||||
RunIntegerProgrammingExampleNaturalApi("SCIP_MIXED_INTEGER_PROGRAMMING");
|
||||
}
|
||||
}
|
||||
229
examples/dotnet/csharp/csjobshop.cs
Normal file
229
examples/dotnet/csharp/csjobshop.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
class Task {
|
||||
public Task(int taskId, int jobId, int duration, int machine) {
|
||||
TaskId = taskId;
|
||||
JobId = jobId;
|
||||
Duration = duration;
|
||||
Machine = machine;
|
||||
Name = "T" + taskId + "J" + jobId + "M" +
|
||||
machine + "D" + duration;
|
||||
}
|
||||
public int TaskId {get; set;}
|
||||
public int JobId {get; set;}
|
||||
public int Machine {get; set;}
|
||||
public int Duration {get; set;}
|
||||
public string Name {get;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class FlexibleJobshop
|
||||
{
|
||||
//Number of machines.
|
||||
public const int machinesCount = 3;
|
||||
//horizon is the upper bound of the start time of all tasks.
|
||||
public const int horizon = 300;
|
||||
//this will be set to the size of myJobList variable.
|
||||
public static int jobsCount;
|
||||
/*Search time limit in milliseconds. if it's equal to 0,
|
||||
then no time limit will be used.*/
|
||||
public const int timeLimitInMs = 0;
|
||||
public static List<List<Task>> myJobList = new List<List<Task>>();
|
||||
public static void InitTaskList() {
|
||||
List<Task> taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 0, 65, 0));
|
||||
taskList.Add(new Task(1 ,0, 5, 1));
|
||||
taskList.Add(new Task(2 ,0, 15, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 1, 15, 0));
|
||||
taskList.Add(new Task(1 ,1, 25, 1));
|
||||
taskList.Add(new Task(2 ,1, 10, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0 ,2, 25, 0));
|
||||
taskList.Add(new Task(1 ,2, 30, 1));
|
||||
taskList.Add(new Task(2 ,2, 40, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 3, 20, 0));
|
||||
taskList.Add(new Task(1 ,3, 35, 1));
|
||||
taskList.Add(new Task(2 ,3, 10, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 4, 15, 0));
|
||||
taskList.Add(new Task(1 ,4, 25, 1));
|
||||
taskList.Add(new Task(2 ,4, 10, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 5, 25, 0));
|
||||
taskList.Add(new Task(1 ,5, 30, 1));
|
||||
taskList.Add(new Task(2 ,5, 40, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 6, 20, 0));
|
||||
taskList.Add(new Task(1 ,6, 35, 1));
|
||||
taskList.Add(new Task(2 ,6, 10, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 7, 10, 0));
|
||||
taskList.Add(new Task(1 ,7, 15, 1));
|
||||
taskList.Add(new Task(2 ,7, 50, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
taskList = new List<Task>();
|
||||
taskList.Add(new Task(0, 8, 50, 0));
|
||||
taskList.Add(new Task(1 ,8, 10, 1));
|
||||
taskList.Add(new Task(2 ,8, 20, 2));
|
||||
myJobList.Add(taskList);
|
||||
|
||||
jobsCount = myJobList.Count;
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
InitTaskList();
|
||||
Solver solver = new Solver("Jobshop");
|
||||
|
||||
// ----- Creates all Intervals and vars -----
|
||||
|
||||
// All tasks
|
||||
List<IntervalVar> allTasks = new List<IntervalVar>();
|
||||
// Stores all tasks attached interval variables per job.
|
||||
List<List<IntervalVar>>
|
||||
jobsToTasks = new List<List<IntervalVar>>(jobsCount);
|
||||
// machinesToTasks stores the same interval variables as above, but
|
||||
// grouped my machines instead of grouped by jobs.
|
||||
List<List<IntervalVar>>
|
||||
machinesToTasks = new List<List<IntervalVar>>(machinesCount);
|
||||
for (int i=0; i<machinesCount; i++) {
|
||||
machinesToTasks.Add(new List<IntervalVar>());
|
||||
}
|
||||
|
||||
// Creates all individual interval variables.
|
||||
foreach (List<Task> job in myJobList) {
|
||||
jobsToTasks.Add(new List<IntervalVar>());
|
||||
foreach (Task task in job) {
|
||||
IntervalVar oneTask = solver.MakeFixedDurationIntervalVar(
|
||||
0, horizon, task.Duration, false, task.Name);
|
||||
jobsToTasks[task.JobId].Add(oneTask);
|
||||
allTasks.Add(oneTask);
|
||||
machinesToTasks[task.Machine].Add(oneTask);
|
||||
}
|
||||
}
|
||||
|
||||
// ----- Creates model -----
|
||||
|
||||
// Creates precedences inside jobs.
|
||||
foreach (List<IntervalVar> jobToTask in jobsToTasks) {
|
||||
int tasksCount = jobToTask.Count;
|
||||
for (int task_index = 0; task_index < tasksCount - 1; ++task_index) {
|
||||
IntervalVar t1 = jobToTask[task_index];
|
||||
IntervalVar t2 = jobToTask[task_index + 1];
|
||||
Constraint prec =
|
||||
solver.MakeIntervalVarRelation(t2, Solver.STARTS_AFTER_END, t1);
|
||||
solver.Add(prec);
|
||||
}
|
||||
}
|
||||
|
||||
// Adds disjunctive constraints on unary resources, and creates
|
||||
// sequence variables. A sequence variable is a dedicated variable
|
||||
// whose job is to sequence interval variables.
|
||||
SequenceVar[] allSequences = new SequenceVar[machinesCount];
|
||||
for (int machineId = 0; machineId < machinesCount; ++machineId) {
|
||||
string name = "Machine_" + machineId;
|
||||
DisjunctiveConstraint ct =
|
||||
solver.MakeDisjunctiveConstraint(machinesToTasks[machineId].ToArray(),
|
||||
name);
|
||||
solver.Add(ct);
|
||||
allSequences[machineId] = ct.SequenceVar();
|
||||
}
|
||||
// Creates array of end_times of jobs.
|
||||
IntVar[] allEnds = new IntVar[jobsCount];
|
||||
for (int i=0; i<jobsCount; i++) {
|
||||
IntervalVar task = jobsToTasks[i].Last();
|
||||
allEnds[i] = task.EndExpr().Var();
|
||||
}
|
||||
|
||||
// Objective: minimize the makespan (maximum end times of all tasks)
|
||||
// of the problem.
|
||||
IntVar objectiveVar = solver.MakeMax(allEnds).Var();
|
||||
OptimizeVar objectiveMonitor = solver.MakeMinimize(objectiveVar, 1);
|
||||
|
||||
// ----- Search monitors and decision builder -----
|
||||
|
||||
// This decision builder will rank all tasks on all machines.
|
||||
DecisionBuilder sequencePhase =
|
||||
solver.MakePhase(allSequences, Solver.SEQUENCE_DEFAULT);
|
||||
|
||||
// After the ranking of tasks, the schedule is still loose and any
|
||||
// task can be postponed at will. But, because the problem is now a PERT
|
||||
// (http://en.wikipedia.org/wiki/Program_Evaluation_and_Review_Technique),
|
||||
// we can schedule each task at its earliest start time. This iscs
|
||||
// conveniently done by fixing the objective variable to its
|
||||
// minimum value.
|
||||
DecisionBuilder objPhase = solver.MakePhase(
|
||||
objectiveVar, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
// The main decision builder (ranks all tasks, then fixes the
|
||||
// objectiveVariable).
|
||||
DecisionBuilder mainPhase = solver.Compose(sequencePhase, objPhase);
|
||||
|
||||
// Search log.
|
||||
const int kLogFrequency = 1000000;
|
||||
SearchMonitor searchLog =
|
||||
solver.MakeSearchLog(kLogFrequency, objectiveMonitor);
|
||||
|
||||
SearchLimit limit = null;
|
||||
if (timeLimitInMs > 0) {
|
||||
limit = solver.MakeTimeLimit(timeLimitInMs);
|
||||
}
|
||||
|
||||
|
||||
SolutionCollector collector = solver.MakeLastSolutionCollector();
|
||||
collector.Add(allSequences);
|
||||
collector.Add(allTasks.ToArray());
|
||||
// Search.
|
||||
bool solutionFound = solver.Solve(mainPhase, searchLog, objectiveMonitor,
|
||||
limit, collector);
|
||||
if(solutionFound) {
|
||||
//The index of the solution from the collector
|
||||
const int SOLUTION_INDEX = 0;
|
||||
Assignment solution = collector.Solution(SOLUTION_INDEX);
|
||||
for (int m = 0; m < machinesCount; ++m) {
|
||||
Console.WriteLine("Machine " + m + " :");
|
||||
SequenceVar seq = allSequences[m];
|
||||
int[] storedSequence = collector.ForwardSequence(SOLUTION_INDEX, seq);
|
||||
foreach (int taskIndex in storedSequence) {
|
||||
IntervalVar task = seq.Interval(taskIndex);
|
||||
long startMin = solution.StartMin(task);
|
||||
long startMax = solution.StartMax(task);
|
||||
if(startMin == startMax) {
|
||||
Console.WriteLine("Task " + task.Name() + " starts at " +
|
||||
startMin + ".");
|
||||
}
|
||||
else {
|
||||
Console.WriteLine("Task " + task.Name() + " starts between " +
|
||||
startMin + " and " + startMax + ".");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
Console.WriteLine("No solution found!");
|
||||
}
|
||||
}
|
||||
}
|
||||
49
examples/dotnet/csharp/csknapsack.cs
Normal file
49
examples/dotnet/csharp/csknapsack.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Algorithms;
|
||||
|
||||
public class CsKnapsack
|
||||
{
|
||||
static void Main()
|
||||
{
|
||||
KnapsackSolver solver = new KnapsackSolver(
|
||||
KnapsackSolver.KNAPSACK_MULTIDIMENSION_BRANCH_AND_BOUND_SOLVER, "test");
|
||||
long[] profits = { 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 };
|
||||
|
||||
long optimalProfit = 7534;
|
||||
|
||||
Console.WriteLine("Solving knapsack with " + profits.Length +
|
||||
" items, and " + weights.GetLength(0) + " dimension");
|
||||
solver.Init(profits, weights, capacities);
|
||||
long computedProfit = solver.Solve();
|
||||
|
||||
Console.WriteLine("Optimal Profit = " + computedProfit + ", expected = " +
|
||||
optimalProfit);
|
||||
}
|
||||
}
|
||||
176
examples/dotnet/csharp/cslinearprogramming.cs
Normal file
176
examples/dotnet/csharp/cslinearprogramming.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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 CsLinearProgramming
|
||||
{
|
||||
private static void RunLinearProgrammingExample(String solverType)
|
||||
{
|
||||
Solver solver = Solver.CreateSolver("IntegerProgramming", solverType);
|
||||
if (solver == null)
|
||||
{
|
||||
Console.WriteLine("Could not create solver " + solverType);
|
||||
return;
|
||||
}
|
||||
// x1, x2 and x3 are continuous non-negative variables.
|
||||
Variable x1 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x1");
|
||||
Variable x2 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x2");
|
||||
Variable x3 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x3");
|
||||
|
||||
// Maximize 10 * x1 + 6 * x2 + 4 * x3.
|
||||
Objective objective = solver.Objective();
|
||||
objective.SetCoefficient(x1, 10);
|
||||
objective.SetCoefficient(x2, 6);
|
||||
objective.SetCoefficient(x3, 4);
|
||||
objective.SetMaximization();
|
||||
|
||||
// x1 + x2 + x3 <= 100.
|
||||
Constraint c0 = solver.MakeConstraint(double.NegativeInfinity, 100.0);
|
||||
c0.SetCoefficient(x1, 1);
|
||||
c0.SetCoefficient(x2, 1);
|
||||
c0.SetCoefficient(x3, 1);
|
||||
|
||||
// 10 * x1 + 4 * x2 + 5 * x3 <= 600.
|
||||
Constraint c1 = solver.MakeConstraint(double.NegativeInfinity, 600.0);
|
||||
c1.SetCoefficient(x1, 10);
|
||||
c1.SetCoefficient(x2, 4);
|
||||
c1.SetCoefficient(x3, 5);
|
||||
|
||||
// 2 * x1 + 2 * x2 + 6 * x3 <= 300.
|
||||
Constraint c2 = solver.MakeConstraint(double.NegativeInfinity, 300.0);
|
||||
c2.SetCoefficient(x1, 2);
|
||||
c2.SetCoefficient(x2, 2);
|
||||
c2.SetCoefficient(x3, 6);
|
||||
|
||||
Console.WriteLine("Number of variables = " + solver.NumVariables());
|
||||
Console.WriteLine("Number of constraints = " + solver.NumConstraints());
|
||||
|
||||
int resultStatus = solver.Solve();
|
||||
|
||||
// Check that the problem has an optimal solution.
|
||||
if (resultStatus != Solver.OPTIMAL) {
|
||||
Console.WriteLine("The problem does not have an optimal solution!");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Problem solved in " + solver.WallTime() +
|
||||
" milliseconds");
|
||||
|
||||
// The objective value of the solution.
|
||||
Console.WriteLine("Optimal objective value = " +
|
||||
solver.Objective().Value());
|
||||
|
||||
// The value of each variable in the solution.
|
||||
Console.WriteLine("x1 = " + x1.SolutionValue());
|
||||
Console.WriteLine("x2 = " + x2.SolutionValue());
|
||||
Console.WriteLine("x3 = " + x3.SolutionValue());
|
||||
|
||||
Console.WriteLine("Advanced usage:");
|
||||
double[] activities = solver.ComputeConstraintActivities();
|
||||
|
||||
Console.WriteLine("Problem solved in " + solver.Iterations() +
|
||||
" iterations");
|
||||
Console.WriteLine("x1: reduced cost = " + x1.ReducedCost());
|
||||
Console.WriteLine("x2: reduced cost = " + x2.ReducedCost());
|
||||
Console.WriteLine("x3: reduced cost = " + x3.ReducedCost());
|
||||
Console.WriteLine("c0: dual value = " + c0.DualValue());
|
||||
Console.WriteLine(" activity = " + activities[c0.Index()]);
|
||||
Console.WriteLine("c1: dual value = " + c1.DualValue());
|
||||
Console.WriteLine(" activity = " + activities[c1.Index()]);
|
||||
Console.WriteLine("c2: dual value = " + c2.DualValue());
|
||||
Console.WriteLine(" activity = " + activities[c2.Index()]);
|
||||
}
|
||||
|
||||
private static void RunLinearProgrammingExampleNaturalApi(
|
||||
String solverType, bool printModel)
|
||||
{
|
||||
Solver solver = Solver.CreateSolver("IntegerProgramming", solverType);
|
||||
if (solver == null)
|
||||
{
|
||||
Console.WriteLine("Could not create solver " + solverType);
|
||||
return;
|
||||
}
|
||||
// x1, x2 and x3 are continuous non-negative variables.
|
||||
Variable x1 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x1");
|
||||
Variable x2 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x2");
|
||||
Variable x3 = solver.MakeNumVar(0.0, double.PositiveInfinity, "x3");
|
||||
|
||||
solver.Maximize(10 * x1 + 6 * x2 + 4 * x3);
|
||||
Constraint c0 = solver.Add(x1 + x2 + x3 <= 100);
|
||||
Constraint c1 = solver.Add(10 * x1 + x2 * 4 + 5 * x3 <= 600);
|
||||
Constraint c2 = solver.Add(2 * x1 + 2 * x2 + 6 * x3 <= 300);
|
||||
|
||||
Console.WriteLine("Number of variables = " + solver.NumVariables());
|
||||
Console.WriteLine("Number of constraints = " + solver.NumConstraints());
|
||||
|
||||
if (printModel) {
|
||||
string model = solver.ExportModelAsLpFormat(false);
|
||||
Console.WriteLine(model);
|
||||
}
|
||||
|
||||
int resultStatus = solver.Solve();
|
||||
|
||||
// Check that the problem has an optimal solution.
|
||||
if (resultStatus != Solver.OPTIMAL) {
|
||||
Console.WriteLine("The problem does not have an optimal solution!");
|
||||
return;
|
||||
}
|
||||
|
||||
Console.WriteLine("Problem solved in " + solver.WallTime() +
|
||||
" milliseconds");
|
||||
|
||||
// The objective value of the solution.
|
||||
Console.WriteLine("Optimal objective value = " +
|
||||
solver.Objective().Value());
|
||||
|
||||
// The value of each variable in the solution.
|
||||
Console.WriteLine("x1 = " + x1.SolutionValue());
|
||||
Console.WriteLine("x2 = " + x2.SolutionValue());
|
||||
Console.WriteLine("x3 = " + x3.SolutionValue());
|
||||
|
||||
Console.WriteLine("Advanced usage:");
|
||||
double[] activities = solver.ComputeConstraintActivities();
|
||||
Console.WriteLine("Problem solved in " + solver.Iterations() +
|
||||
" iterations");
|
||||
Console.WriteLine("x1: reduced cost = " + x1.ReducedCost());
|
||||
Console.WriteLine("x2: reduced cost = " + x2.ReducedCost());
|
||||
Console.WriteLine("x3: reduced cost = " + x3.ReducedCost());
|
||||
Console.WriteLine("c0: dual value = " + c0.DualValue());
|
||||
Console.WriteLine(" activity = " + activities[c0.Index()]);
|
||||
Console.WriteLine("c1: dual value = " + c1.DualValue());
|
||||
Console.WriteLine(" activity = " + activities[c1.Index()]);
|
||||
Console.WriteLine("c2: dual value = " + c2.DualValue());
|
||||
Console.WriteLine(" activity = " + activities[c2.Index()]);
|
||||
}
|
||||
|
||||
static void Main()
|
||||
{
|
||||
Console.WriteLine("---- Linear programming example with GLOP ----");
|
||||
RunLinearProgrammingExample("GLOP_LINEAR_PROGRAMMING");
|
||||
Console.WriteLine("---- Linear programming example with GLPK ----");
|
||||
RunLinearProgrammingExample("GLPK_LINEAR_PROGRAMMING");
|
||||
Console.WriteLine("---- Linear programming example with CLP ----");
|
||||
RunLinearProgrammingExample("CLP_LINEAR_PROGRAMMING");
|
||||
Console.WriteLine(
|
||||
"---- Linear programming example (Natural API) with GLOP ----");
|
||||
RunLinearProgrammingExampleNaturalApi("GLOP_LINEAR_PROGRAMMING", true);
|
||||
Console.WriteLine(
|
||||
"---- Linear programming example (Natural API) with GLPK ----");
|
||||
RunLinearProgrammingExampleNaturalApi("GLPK_LINEAR_PROGRAMMING", false);
|
||||
Console.WriteLine(
|
||||
"---- Linear programming example (Natural API) with CLP ----");
|
||||
RunLinearProgrammingExampleNaturalApi("CLP_LINEAR_PROGRAMMING", false);
|
||||
}
|
||||
}
|
||||
192
examples/dotnet/csharp/csls_api.cs
Normal file
192
examples/dotnet/csharp/csls_api.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.ConstraintSolver;
|
||||
|
||||
/**
|
||||
* Shows how to write a custom lns operator.
|
||||
*/
|
||||
|
||||
public class OneVarLns : BaseLns
|
||||
{
|
||||
public OneVarLns(IntVar[] vars) : base(vars) {}
|
||||
|
||||
public override void InitFragments()
|
||||
{
|
||||
index_ = 0;
|
||||
}
|
||||
|
||||
public override bool NextFragment()
|
||||
{
|
||||
int size = Size();
|
||||
if (index_ < size)
|
||||
{
|
||||
AppendToFragment(index_);
|
||||
++index_;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private int index_;
|
||||
}
|
||||
|
||||
class MoveOneVar : IntVarLocalSearchOperator {
|
||||
public MoveOneVar(IntVar[] variables) : base(variables)
|
||||
{
|
||||
variable_index_ = 0;
|
||||
move_up_ = false;
|
||||
}
|
||||
|
||||
protected override bool MakeOneNeighbor()
|
||||
{
|
||||
long current_value = OldValue(variable_index_);
|
||||
if (move_up_)
|
||||
{
|
||||
SetValue(variable_index_, current_value + 1);
|
||||
variable_index_ = (variable_index_ + 1) % Size();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetValue(variable_index_, current_value - 1);
|
||||
}
|
||||
move_up_ = !move_up_;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Index of the next variable to try to restore
|
||||
private long variable_index_;
|
||||
// Direction of the modification.
|
||||
private bool move_up_;
|
||||
};
|
||||
|
||||
public class SumFilter : IntVarLocalSearchFilter {
|
||||
public SumFilter(IntVar[] vars) : base(vars)
|
||||
{
|
||||
sum_ = 0;
|
||||
}
|
||||
|
||||
protected override void OnSynchronize(Assignment delta)
|
||||
{
|
||||
sum_ = 0;
|
||||
for (int index = 0; index < Size(); ++index)
|
||||
{
|
||||
sum_ += Value(index);
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Accept(Assignment delta, Assignment unused_deltadelta) {
|
||||
AssignmentIntContainer solution_delta = delta.IntVarContainer();
|
||||
int solution_delta_size = solution_delta.Size();
|
||||
|
||||
for (int i = 0; i < solution_delta_size; ++i)
|
||||
{
|
||||
if (!solution_delta.Element(i).Activated())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
long new_sum = sum_;
|
||||
for (int index = 0; index < solution_delta_size; ++index)
|
||||
{
|
||||
int touched_var = Index(solution_delta.Element(index).Var());
|
||||
long old_value = Value(touched_var);
|
||||
long new_value = solution_delta.Element(index).Value();
|
||||
new_sum += new_value - old_value;
|
||||
}
|
||||
return new_sum < sum_;
|
||||
}
|
||||
|
||||
private long sum_;
|
||||
};
|
||||
|
||||
public class CsLsApi
|
||||
{
|
||||
private static void BasicLns()
|
||||
{
|
||||
Console.WriteLine("BasicLns");
|
||||
Solver solver = new Solver("BasicLns");
|
||||
IntVar[] vars = solver.MakeIntVarArray(4, 0, 4, "vars");
|
||||
IntVar sum_var = vars.Sum().Var();
|
||||
OptimizeVar obj = sum_var.Minimize(1);
|
||||
DecisionBuilder db = solver.MakePhase(vars,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
OneVarLns one_var_lns = new OneVarLns(vars);
|
||||
LocalSearchPhaseParameters ls_params =
|
||||
solver.MakeLocalSearchPhaseParameters(one_var_lns, db);
|
||||
DecisionBuilder ls = solver.MakeLocalSearchPhase(vars, db, ls_params);
|
||||
SolutionCollector collector = solver.MakeLastSolutionCollector();
|
||||
collector.AddObjective(sum_var);
|
||||
SearchMonitor log = solver.MakeSearchLog(1000, obj);
|
||||
solver.Solve(ls, collector, obj, log);
|
||||
Console.WriteLine("Objective value = {0}", collector.ObjectiveValue(0));
|
||||
}
|
||||
|
||||
private static void BasicLs()
|
||||
{
|
||||
Console.WriteLine("BasicLs");
|
||||
Solver solver = new Solver("BasicLs");
|
||||
IntVar[] vars = solver.MakeIntVarArray(4, 0, 4, "vars");
|
||||
IntVar sum_var = vars.Sum().Var();
|
||||
OptimizeVar obj = sum_var.Minimize(1);
|
||||
DecisionBuilder db = solver.MakePhase(vars,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
MoveOneVar move_one_var = new MoveOneVar(vars);
|
||||
LocalSearchPhaseParameters ls_params =
|
||||
solver.MakeLocalSearchPhaseParameters(move_one_var, db);
|
||||
DecisionBuilder ls = solver.MakeLocalSearchPhase(vars, db, ls_params);
|
||||
SolutionCollector collector = solver.MakeLastSolutionCollector();
|
||||
collector.AddObjective(sum_var);
|
||||
SearchMonitor log = solver.MakeSearchLog(1000, obj);
|
||||
solver.Solve(ls, collector, obj, log);
|
||||
Console.WriteLine("Objective value = {0}", collector.ObjectiveValue(0));
|
||||
}
|
||||
|
||||
private static void BasicLsWithFilter()
|
||||
{
|
||||
Console.WriteLine("BasicLsWithFilter");
|
||||
Solver solver = new Solver("BasicLs");
|
||||
IntVar[] vars = solver.MakeIntVarArray(4, 0, 4, "vars");
|
||||
IntVar sum_var = vars.Sum().Var();
|
||||
OptimizeVar obj = sum_var.Minimize(1);
|
||||
DecisionBuilder db = solver.MakePhase(vars,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
MoveOneVar move_one_var = new MoveOneVar(vars);
|
||||
SumFilter filter = new SumFilter(vars);
|
||||
IntVarLocalSearchFilter[] filters =
|
||||
new IntVarLocalSearchFilter[] { filter };
|
||||
LocalSearchPhaseParameters ls_params =
|
||||
solver.MakeLocalSearchPhaseParameters(move_one_var, db, null, filters);
|
||||
DecisionBuilder ls = solver.MakeLocalSearchPhase(vars, db, ls_params);
|
||||
SolutionCollector collector = solver.MakeLastSolutionCollector();
|
||||
collector.AddObjective(sum_var);
|
||||
SearchMonitor log = solver.MakeSearchLog(1000, obj);
|
||||
solver.Solve(ls, collector, obj, log);
|
||||
Console.WriteLine("Objective value = {0}", collector.ObjectiveValue(0));
|
||||
}
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
BasicLns();
|
||||
BasicLs();
|
||||
BasicLsWithFilter();
|
||||
}
|
||||
}
|
||||
73
examples/dotnet/csharp/csrabbitspheasants.cs
Normal file
73
examples/dotnet/csharp/csrabbitspheasants.cs
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.ConstraintSolver;
|
||||
|
||||
/**
|
||||
* Shows how to write a custom decision builder.
|
||||
*/
|
||||
public class AssignFirstUnboundToMin : NetDecisionBuilder
|
||||
{
|
||||
public AssignFirstUnboundToMin(IntVar[] vars)
|
||||
{
|
||||
vars_ = vars;
|
||||
}
|
||||
|
||||
public override Decision Next(Solver solver)
|
||||
{
|
||||
foreach (IntVar var in vars_)
|
||||
{
|
||||
if (!var.Bound())
|
||||
{
|
||||
return solver.MakeAssignVariableValue(var, var.Min());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private IntVar[] vars_;
|
||||
}
|
||||
|
||||
|
||||
public class CsRabbitsPheasants
|
||||
{
|
||||
/**
|
||||
* Solves the rabbits + pheasants problem. We are seing 20 heads
|
||||
* and 56 legs. How many rabbits and how many pheasants are we thus
|
||||
* seeing?
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("RabbitsPheasants");
|
||||
IntVar rabbits = solver.MakeIntVar(0, 100, "rabbits");
|
||||
IntVar pheasants = solver.MakeIntVar(0, 100, "pheasants");
|
||||
solver.Add(rabbits + pheasants == 20);
|
||||
solver.Add(rabbits * 4 + pheasants * 2 == 56);
|
||||
DecisionBuilder db =
|
||||
new AssignFirstUnboundToMin(new IntVar[] {rabbits, pheasants});
|
||||
solver.NewSearch(db);
|
||||
solver.NextSolution();
|
||||
Console.WriteLine(
|
||||
"Solved Rabbits + Pheasants in {0} ms, and {1} search tree branches.",
|
||||
solver.WallTime(), solver.Branches());
|
||||
Console.WriteLine(rabbits.ToString());
|
||||
Console.WriteLine(pheasants.ToString());
|
||||
solver.EndSearch();
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
120
examples/dotnet/csharp/cstsp.cs
Normal file
120
examples/dotnet/csharp/cstsp.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Generic;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
class Tsp
|
||||
{
|
||||
class RandomManhattan : NodeEvaluator2 {
|
||||
public RandomManhattan(int size, int seed)
|
||||
{
|
||||
this.xs_ = new int[size];
|
||||
this.ys_ = new int[size];
|
||||
Random generator = new Random(seed);
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
xs_[i] = generator.Next(1000);
|
||||
ys_[i] = generator.Next(1000);
|
||||
}
|
||||
}
|
||||
|
||||
public override long Run(int first_index, int second_index) {
|
||||
return Math.Abs(xs_[first_index] - xs_[second_index]) +
|
||||
Math.Abs(ys_[first_index] - ys_[second_index]);
|
||||
}
|
||||
|
||||
private int[] xs_;
|
||||
private int[] ys_;
|
||||
};
|
||||
|
||||
class ConstantCallback : NodeEvaluator2 {
|
||||
public override long Run(int first_index, int second_index) {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
static void Solve(int size, int forbidden, int seed)
|
||||
{
|
||||
RoutingModel routing = new RoutingModel(size, 1, 0);
|
||||
|
||||
// Setting the cost function.
|
||||
// Put a permanent callback to the distance accessor here. The callback
|
||||
// has the following signature: ResultCallback2<int64, int64, int64>.
|
||||
// The two arguments are the from and to node inidices.
|
||||
RandomManhattan distances = new RandomManhattan(size, seed);
|
||||
routing.SetCost(distances);
|
||||
|
||||
// Forbid node connections (randomly).
|
||||
Random randomizer = new Random();
|
||||
long forbidden_connections = 0;
|
||||
while (forbidden_connections < forbidden) {
|
||||
long from = randomizer.Next(size - 1);
|
||||
long to = randomizer.Next(size - 1) + 1;
|
||||
if (routing.NextVar(from).Contains(to)) {
|
||||
Console.WriteLine("Forbidding connection {0} -> {1}", from, to);
|
||||
routing.NextVar(from).RemoveValue(to);
|
||||
++forbidden_connections;
|
||||
}
|
||||
}
|
||||
|
||||
// Add dummy dimension to test API.
|
||||
routing.AddDimension(new ConstantCallback(),
|
||||
size + 1,
|
||||
size + 1,
|
||||
true,
|
||||
"dummy");
|
||||
|
||||
// Solve, returns a solution if any (owned by RoutingModel).
|
||||
RoutingSearchParameters search_parameters =
|
||||
RoutingModel.DefaultSearchParameters();
|
||||
// Setting first solution heuristic (cheapest addition).
|
||||
search_parameters.FirstSolutionStrategy =
|
||||
FirstSolutionStrategy.Types.Value.PathCheapestArc;
|
||||
|
||||
Assignment solution = routing.SolveWithParameters(search_parameters);
|
||||
Console.WriteLine("Status = {0}", routing.Status());
|
||||
if (solution != null) {
|
||||
// Solution cost.
|
||||
Console.WriteLine("Cost = {0}", solution.ObjectiveValue());
|
||||
// Inspect solution.
|
||||
// Only one route here; otherwise iterate from 0 to routing.vehicles() - 1
|
||||
int route_number = 0;
|
||||
for (long node = routing.Start(route_number);
|
||||
!routing.IsEnd(node);
|
||||
node = solution.Value(routing.NextVar(node))) {
|
||||
Console.Write("{0} -> ", node);
|
||||
}
|
||||
Console.WriteLine("0");
|
||||
}
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
int size = 10;
|
||||
if (args.Length > 0) {
|
||||
size = Convert.ToInt32(args[0]);
|
||||
}
|
||||
int forbidden = 0;
|
||||
if (args.Length > 0) {
|
||||
forbidden = Convert.ToInt32(args[1]);
|
||||
}
|
||||
int seed = 0;
|
||||
if (args.Length > 2) {
|
||||
seed = Convert.ToInt32(args[2]);
|
||||
}
|
||||
|
||||
Solve(size, forbidden, seed);
|
||||
}
|
||||
}
|
||||
122
examples/dotnet/csharp/curious_set_of_integers.cs
Normal file
122
examples/dotnet/csharp/curious_set_of_integers.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// 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 CuriousSetOfIntegers
|
||||
{
|
||||
|
||||
|
||||
public static void Decreasing(Solver solver, IntVar[] x) {
|
||||
for(int i = 0; i < x.Length - 1; i++) {
|
||||
solver.Add(x[i] <= x[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Crypto problem in Google CP Solver.
|
||||
*
|
||||
* Martin Gardner (February 1967):
|
||||
* """
|
||||
* The integers 1,3,8, and 120 form a set with a remarkable property: the
|
||||
* product of any two integers is one less than a perfect square. Find
|
||||
* a fifth number that can be added to the set without destroying
|
||||
* this property.
|
||||
* """
|
||||
*
|
||||
* Also see, http://www.hakank.org/or-tools/curious_set_of_integers.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("CuriousSetOfIntegers");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int n = 5;
|
||||
int max_val = 10000;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, max_val, "x");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
for(int i = 0; i < n - 1; i++) {
|
||||
for(int j = i + 1; j < n; j++) {
|
||||
IntVar p = solver.MakeIntVar(0, max_val);
|
||||
solver.Add((p.Square() - 1) - (x[i] * x[j]) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Symmetry breaking
|
||||
Decreasing(solver, x);
|
||||
|
||||
// This is the original problem
|
||||
// Which is the fifth number?
|
||||
int[] v = {1,3,8,120};
|
||||
IntVar[] b = (from i in Enumerable.Range(0, n)
|
||||
select x[i].IsMember(v)).ToArray();
|
||||
solver.Add(b.Sum() == 4);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Solve();
|
||||
|
||||
}
|
||||
}
|
||||
202
examples/dotnet/csharp/debruijn.cs
Normal file
202
examples/dotnet/csharp/debruijn.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class DeBruijn
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* ToNum(solver, a, num, base)
|
||||
*
|
||||
* channelling between the array a and the number num.
|
||||
*
|
||||
*/
|
||||
private static Constraint ToNum(IntVar[] a, IntVar num, int bbase) {
|
||||
int len = a.Length;
|
||||
|
||||
IntVar[] tmp = new IntVar[len];
|
||||
for(int i = 0; i < len; i++) {
|
||||
tmp[i] = (a[i]*(int)Math.Pow(bbase,(len-i-1))).Var();
|
||||
}
|
||||
return tmp.Sum() == num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Implements "arbitrary" de Bruijn sequences.
|
||||
* See http://www.hakank.org/or-tools/debruijn_binary.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int bbase, int n, int m)
|
||||
{
|
||||
Solver solver = new Solver("DeBruijn");
|
||||
|
||||
|
||||
// Ensure that the number of each digit in bin_code is
|
||||
// the same. Nice feature, but it can slow things down...
|
||||
bool check_same_gcc = false; // true;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(m, 0, (int)Math.Pow(bbase, n) - 1, "x");
|
||||
IntVar[,] binary = solver.MakeIntVarMatrix(m, n, 0, bbase - 1, "binary");
|
||||
|
||||
// this is the de Bruijn sequence
|
||||
IntVar[] bin_code =
|
||||
solver.MakeIntVarArray(m, 0, bbase - 1, "bin_code");
|
||||
|
||||
// occurences of each number in bin_code
|
||||
IntVar[] gcc = solver.MakeIntVarArray(bbase, 0, m, "gcc");
|
||||
|
||||
// for the branching
|
||||
IntVar[] all = new IntVar[2 * m + bbase];
|
||||
for(int i = 0; i < m; i++) {
|
||||
all[i] = x[i];
|
||||
all[m + i] = bin_code[i];
|
||||
}
|
||||
for(int i = 0; i < bbase; i++) {
|
||||
all[2 * m + i] = gcc[i];
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
// converts x <-> binary
|
||||
for(int i = 0; i < m; i++) {
|
||||
IntVar[] t = new IntVar[n];
|
||||
for(int j = 0; j < n; j++) {
|
||||
t[j] = binary[i,j];
|
||||
}
|
||||
solver.Add(ToNum(t, x[i], bbase));
|
||||
}
|
||||
|
||||
// the de Bruijn condition:
|
||||
// the first elements in binary[i] is the same as the last
|
||||
// elements in binary[i-1]
|
||||
for(int i = 1; i < m; i++) {
|
||||
for(int j = 1; j < n; j++) {
|
||||
solver.Add(binary[i - 1,j] == binary[i,j - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// ... and around the corner
|
||||
for(int j = 1; j < n; j++) {
|
||||
solver.Add(binary[m - 1,j] == binary[0,j - 1]);
|
||||
}
|
||||
|
||||
// converts binary -> bin_code (de Bruijn sequence)
|
||||
for(int i = 0; i < m; i++) {
|
||||
solver.Add(bin_code[i] == binary[i,0]);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// extra: ensure that all the numbers in the de Bruijn sequence
|
||||
// (bin_code) has the same occurrences (if check_same_gcc is True
|
||||
// and mathematically possible)
|
||||
solver.Add(bin_code.Distribute(gcc));
|
||||
if (check_same_gcc && m % bbase == 0) {
|
||||
for(int i = 1; i < bbase; i++) {
|
||||
solver.Add(gcc[i] == gcc[i - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
// symmetry breaking:
|
||||
// the minimum value of x should be first
|
||||
// solver.Add(x[0] == x.Min());
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < m; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
|
||||
Console.Write("\nde Bruijn sequence:");
|
||||
for(int i = 0; i < m; i++) {
|
||||
Console.Write(bin_code[i].Value() + " ");
|
||||
}
|
||||
|
||||
Console.Write("\ngcc: ");
|
||||
for(int i = 0; i < bbase; i++) {
|
||||
Console.Write(gcc[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
|
||||
|
||||
// for debugging etc: show the full binary table
|
||||
/*
|
||||
Console.Write("binary:");
|
||||
for(int i = 0; i < m; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write(binary[i][j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
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 bbase = 2;
|
||||
int n = 3;
|
||||
int m = 8;
|
||||
|
||||
if (args.Length > 0) {
|
||||
bbase = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (args.Length > 1) {
|
||||
n = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
if (args.Length > 2) {
|
||||
m = Convert.ToInt32(args[2]);
|
||||
}
|
||||
|
||||
Solve(bbase, n, m);
|
||||
}
|
||||
}
|
||||
101
examples/dotnet/csharp/diet.cs
Normal file
101
examples/dotnet/csharp/diet.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Diet
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solves the Diet problem
|
||||
*
|
||||
* See http://www.hakank.org/google_or_tools/diet1.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Diet");
|
||||
|
||||
int n = 4;
|
||||
int[] price = { 50, 20, 30, 80}; // in cents
|
||||
|
||||
// requirements for each nutrition type
|
||||
int[] limits = {500, 6, 10, 8};
|
||||
string[] products = {"A", "B", "C", "D"};
|
||||
|
||||
// nutritions for each product
|
||||
int[] calories = {400, 200, 150, 500};
|
||||
int[] chocolate = {3, 2, 0, 0};
|
||||
int[] sugar = {2, 2, 4, 4};
|
||||
int[] fat = {2, 4, 1, 5};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, 100, "x");
|
||||
IntVar cost = x.ScalProd(price).Var();
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// solver.Add(solver.MakeScalProdGreaterOrEqual(x, calories, limits[0]));
|
||||
solver.Add(x.ScalProd(calories) >= limits[0]);
|
||||
solver.Add(x.ScalProd(chocolate) >= limits[1]);
|
||||
solver.Add(x.ScalProd(sugar) >= limits[2]);
|
||||
solver.Add(x.ScalProd(fat) >= limits[3]);
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = cost.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_PATH,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("cost: {0}", cost.Value());
|
||||
Console.WriteLine("Products: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.WriteLine("{0}: {1}", products[i], x[i].Value());
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
216
examples/dotnet/csharp/discrete_tomography.cs
Normal file
216
examples/dotnet/csharp/discrete_tomography.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
//
|
||||
// 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 DiscreteTomography
|
||||
{
|
||||
|
||||
// default problem
|
||||
static int[] default_rowsums = {0,0,8,2,6,4,5,3,7,0,0};
|
||||
static int[] default_colsums = {0,0,7,1,6,3,4,5,2,7,0,0};
|
||||
|
||||
static int[] rowsums2;
|
||||
static int[] colsums2;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Discrete tomography
|
||||
*
|
||||
* Problem from http://eclipse.crosscoreop.com/examples/tomo.ecl.txt
|
||||
* """
|
||||
* This is a little 'tomography' problem, taken from an old issue
|
||||
* of Scientific American.
|
||||
*
|
||||
* A matrix which contains zeroes and ones gets "x-rayed" vertically and
|
||||
* horizontally, giving the total number of ones in each row and column.
|
||||
* The problem is to reconstruct the contents of the matrix from this
|
||||
* information. Sample run:
|
||||
*
|
||||
* ?- go.
|
||||
* 0 0 7 1 6 3 4 5 2 7 0 0
|
||||
* 0
|
||||
* 0
|
||||
* 8 * * * * * * * *
|
||||
* 2 * *
|
||||
* 6 * * * * * *
|
||||
* 4 * * * *
|
||||
* 5 * * * * *
|
||||
* 3 * * *
|
||||
* 7 * * * * * * *
|
||||
* 0
|
||||
* 0
|
||||
*
|
||||
* Eclipse solution by Joachim Schimpf, IC-Parc
|
||||
* """
|
||||
*
|
||||
* See http://www.hakank.org/or-tools/discrete_tomography.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int[] rowsums, int[] colsums)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("DiscreteTomography");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int r = rowsums.Length;
|
||||
int c = colsums.Length;
|
||||
|
||||
Console.Write("rowsums: ");
|
||||
for(int i = 0; i < r; i++) {
|
||||
Console.Write(rowsums[i] + " ");
|
||||
}
|
||||
Console.Write("\ncolsums: ");
|
||||
for(int j = 0; j < c; j++) {
|
||||
Console.Write(colsums[j] + " ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(r, c, 0, 1, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// row sums
|
||||
for(int i = 0; i < r; i++) {
|
||||
var tmp = from j in Enumerable.Range(0, c) select x[i,j];
|
||||
solver.Add(tmp.ToArray().Sum() == rowsums[i]);
|
||||
}
|
||||
|
||||
// cols sums
|
||||
for(int j = 0; j < c; j++) {
|
||||
var tmp = from i in Enumerable.Range(0, r) select x[i,j];
|
||||
solver.Add(tmp.ToArray().Sum() == colsums[j]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < r; i++) {
|
||||
for(int j = 0; j < c; j++) {
|
||||
Console.Write("{0} ", x[i,j].Value() == 1 ? "#" : "." );
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Reads a discrete tomography file.
|
||||
* File format:
|
||||
* # a comment which is ignored
|
||||
* % a comment which also is ignored
|
||||
* rowsums separated by [,\s]
|
||||
* colsums separated by [,\s]
|
||||
*
|
||||
* e.g.
|
||||
* """
|
||||
* 0,0,8,2,6,4,5,3,7,0,0
|
||||
* 0,0,7,1,6,3,4,5,2,7,0,0
|
||||
* # comment
|
||||
* % another comment
|
||||
* """
|
||||
*
|
||||
*/
|
||||
private static void readFile(String file) {
|
||||
|
||||
Console.WriteLine("readFile(" + file + ")");
|
||||
|
||||
TextReader inr = new StreamReader(file);
|
||||
String str;
|
||||
int lineCount = 0;
|
||||
while ((str = inr.ReadLine()) != null && str.Length > 0) {
|
||||
str = str.Trim();
|
||||
|
||||
// ignore comments
|
||||
if(str.StartsWith("#") || str.StartsWith("%")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lineCount == 0) {
|
||||
rowsums2 = ConvLine(str);
|
||||
} else if (lineCount == 1) {
|
||||
colsums2 = ConvLine(str);
|
||||
break;
|
||||
}
|
||||
|
||||
lineCount++;
|
||||
|
||||
} // end while
|
||||
|
||||
inr.Close();
|
||||
|
||||
} // end readFile
|
||||
|
||||
|
||||
private static int[] ConvLine(String str) {
|
||||
String[] tmp = Regex.Split(str, "[,\\s]+");
|
||||
int len = tmp.Length;
|
||||
int[] sums = new int[len];
|
||||
for(int i = 0; i < len; i++) {
|
||||
sums[i] = Convert.ToInt32(tmp[i]);
|
||||
}
|
||||
|
||||
return sums;
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
|
||||
if(args.Length > 0) {
|
||||
readFile(args[0]);
|
||||
Solve(rowsums2, colsums2);
|
||||
} else {
|
||||
Solve(default_rowsums, default_colsums);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
192
examples/dotnet/csharp/divisible_by_9_through_1.cs
Normal file
192
examples/dotnet/csharp/divisible_by_9_through_1.cs
Normal file
@@ -0,0 +1,192 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class DivisibleBy9Through1
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* A simple propagator for modulo constraint.
|
||||
*
|
||||
* This implementation is based on the ECLiPSe version
|
||||
* mentioned in "A Modulo propagator for ECLiPSE"
|
||||
* http://www.hakank.org/constraint_programming_blog/2010/05/a_modulo_propagator_for_eclips.html
|
||||
* The ECLiPSe Prolog source code:
|
||||
* http://www.hakank.org/eclipse/modulo_propagator.ecl
|
||||
*
|
||||
*/
|
||||
public static void MyMod(Solver solver, IntVar x, IntVar y, IntVar r) {
|
||||
|
||||
long lbx = x.Min();
|
||||
long ubx = x.Max();
|
||||
long ubx_neg = -ubx;
|
||||
long lbx_neg = -lbx;
|
||||
int min_x = (int)Math.Min(lbx, ubx_neg);
|
||||
int max_x = (int)Math.Max(ubx, lbx_neg);
|
||||
|
||||
IntVar d = solver.MakeIntVar(min_x, max_x, "d");
|
||||
|
||||
// r >= 0
|
||||
solver.Add(r >= 0);
|
||||
|
||||
// x*r >= 0
|
||||
solver.Add( x*r >= 0);
|
||||
|
||||
// -abs(y) < r
|
||||
solver.Add(-y.Abs() < r);
|
||||
|
||||
// r < abs(y)
|
||||
solver.Add(r < y.Abs());
|
||||
|
||||
// min_x <= d, i.e. d > min_x
|
||||
solver.Add(d > min_x);
|
||||
|
||||
// d <= max_x
|
||||
solver.Add(d <= max_x);
|
||||
|
||||
// x == y*d+r
|
||||
solver.Add(x - (y*d + r) == 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* ToNum(solver, a, num, base)
|
||||
*
|
||||
* channelling between the array a and the number num
|
||||
*
|
||||
*/
|
||||
private static Constraint ToNum(IntVar[] a, IntVar num, int bbase) {
|
||||
int len = a.Length;
|
||||
|
||||
IntVar[] tmp = new IntVar[len];
|
||||
for(int i = 0; i < len; i++) {
|
||||
tmp[i] = (a[i]*(int)Math.Pow(bbase,(len-i-1))).Var();
|
||||
}
|
||||
return tmp.Sum() == num;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves the divisible by 9 through 1 problem.
|
||||
* See http://www.hakank.org/google_or_tools/divisible_by_9_through_1.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int bbase)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("DivisibleBy9Through1");
|
||||
|
||||
|
||||
int m = (int)Math.Pow(bbase,(bbase-1)) - 1;
|
||||
int n = bbase - 1;
|
||||
|
||||
String[] digits_str = {"_","0","1","2","3","4","5","6","7","8","9"};
|
||||
|
||||
Console.WriteLine("base: " + bbase);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
// digits
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 1, bbase - 1, "x");
|
||||
|
||||
// the numbers. t[0] contains the answe
|
||||
IntVar[] t = solver.MakeIntVarArray(n, 0, m, "t");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
// Ensure the divisibility of base .. 1
|
||||
IntVar zero = solver.MakeIntConst(0);
|
||||
for(int i = 0; i < n; i++) {
|
||||
int mm = bbase - i - 1;
|
||||
IntVar[] tt = new IntVar[mm];
|
||||
for(int j = 0; j < mm; j++) {
|
||||
tt[j] = x[j];
|
||||
}
|
||||
solver.Add(ToNum(tt, t[i], bbase));
|
||||
MyMod(solver, t[i], solver.MakeIntConst(mm), zero);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine("\nt: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(t[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
|
||||
if (bbase != 10) {
|
||||
Console.Write("Number base 10: " + t[0].Value());
|
||||
Console.Write(" Base " + bbase + ": ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(digits_str[(int)x[i].Value() + 1]);
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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 bbase = 10;
|
||||
if (args.Length > 0) {
|
||||
bbase = Convert.ToInt32(args[0]);
|
||||
if (bbase > 12) {
|
||||
// Though base = 12 has no solution...
|
||||
Console.WriteLine("Sorry, max relevant base is 12. Setting base to 12.");
|
||||
bbase = 10;
|
||||
}
|
||||
}
|
||||
|
||||
Solve(bbase);
|
||||
}
|
||||
}
|
||||
122
examples/dotnet/csharp/dudeney.cs
Normal file
122
examples/dotnet/csharp/dudeney.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// 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 DudeneyNumbers
|
||||
{
|
||||
|
||||
|
||||
private static Constraint ToNum(IntVar[] a, IntVar num, int bbase) {
|
||||
int len = a.Length;
|
||||
|
||||
IntVar[] tmp = new IntVar[len];
|
||||
for(int i = 0; i < len; i++) {
|
||||
tmp[i] = (a[i]*(int)Math.Pow(bbase,(len-i-1))).Var();
|
||||
}
|
||||
return tmp.Sum() == num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Dudeney numbers
|
||||
* From Pierre Schaus blog post
|
||||
* Dudeney number
|
||||
* http://cp-is-fun.blogspot.com/2010/09/test-python.html
|
||||
* """
|
||||
* I discovered yesterday Dudeney Numbers
|
||||
* A Dudeney Numbers is a positive integer that is a perfect cube such that the sum
|
||||
* of its decimal digits is equal to the cube root of the number. There are only six
|
||||
* Dudeney Numbers and those are very easy to find with CP.
|
||||
* I made my first experience with google cp solver so find these numbers (model below)
|
||||
* and must say that I found it very convenient to build CP models in python!
|
||||
* When you take a close look at the line:
|
||||
* solver.Add(sum([10**(n-i-1)*x[i] for i in range(n)]) == nb)
|
||||
* It is difficult to argue that it is very far from dedicated
|
||||
* optimization languages!
|
||||
* """
|
||||
*
|
||||
* Also see: http://en.wikipedia.org/wiki/Dudeney_number
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("DudeneyNumbers");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int n = 6;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, 9, "x");
|
||||
IntVar nb = solver.MakeIntVar(3, (int)Math.Pow(10,n), "nb");
|
||||
IntVar s = solver.MakeIntVar(1,9*n+1,"s");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(nb == s*s*s);
|
||||
solver.Add(x.Sum() == s);
|
||||
|
||||
// solver.Add(ToNum(x, nb, 10));
|
||||
|
||||
// alternative
|
||||
solver.Add((from i in Enumerable.Range(0, n)
|
||||
select (x[i]*(int)Math.Pow(10,n-i-1)).Var()).
|
||||
ToArray().Sum() == nb);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine(nb.Value());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Solve();
|
||||
|
||||
}
|
||||
}
|
||||
228
examples/dotnet/csharp/einav_puzzle2.cs
Normal file
228
examples/dotnet/csharp/einav_puzzle2.cs
Normal file
@@ -0,0 +1,228 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class EinavPuzzle2
|
||||
{
|
||||
/**
|
||||
*
|
||||
* A programming puzzle from Einav.
|
||||
*
|
||||
* From
|
||||
* "A programming puzzle from Einav"
|
||||
* http://gcanyon.wordpress.com/2009/10/28/a-programming-puzzle-from-einav/
|
||||
* """
|
||||
* My friend Einav gave me this programming puzzle to work on. Given
|
||||
* this array of positive and negative numbers:
|
||||
* 33 30 -10 -6 18 7 -11 -23 6
|
||||
* ...
|
||||
* -25 4 16 30 33 -23 -4 4 -23
|
||||
*
|
||||
* You can flip the sign of entire rows and columns, as many of them
|
||||
* as you like. The goal is to make all the rows and columns sum to positive
|
||||
* numbers (or zero), and then to find the solution (there are more than one)
|
||||
* that has the smallest overall sum. So for example, for this array:
|
||||
* 33 30 -10
|
||||
* -16 19 9
|
||||
* -17 -12 -14
|
||||
* You could flip the sign for the bottom row to get this array:
|
||||
* 33 30 -10
|
||||
* -16 19 9
|
||||
* 17 12 14
|
||||
* Now all the rows and columns have positive sums, and the overall total is
|
||||
* 108.
|
||||
* But you could instead flip the second and third columns, and the second
|
||||
* row, to get this array:
|
||||
* 33 -30 10
|
||||
* 16 19 9
|
||||
* -17 12 14
|
||||
* All the rows and columns still total positive, and the overall sum is just
|
||||
* 66. So this solution is better (I don't know if it's the best)
|
||||
* A pure brute force solution would have to try over 30 billion solutions.
|
||||
* I wrote code to solve this in J. I'll post that separately.
|
||||
* """
|
||||
*
|
||||
* Note:
|
||||
* This is a port of Larent Perrons's Python version of my own einav_puzzle.py.
|
||||
* He removed some of the decision variables and made it more efficient.
|
||||
* Thanks!
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/einav_puzzle2.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("EinavPuzzle2");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
|
||||
// Small problem
|
||||
// int rows = 3;
|
||||
// int cols = 3;
|
||||
// int[,] data = {
|
||||
// { 33, 30, -10},
|
||||
// {-16, 19, 9},
|
||||
// {-17, -12, -14}
|
||||
// };
|
||||
|
||||
|
||||
// Full problem
|
||||
int rows = 27;
|
||||
int cols = 9;
|
||||
int[,] data = {
|
||||
{33,30,10,-6,18,-7,-11,23,-6},
|
||||
{16,-19,9,-26,-8,-19,-8,-21,-14},
|
||||
{17,12,-14,31,-30,13,-13,19,16},
|
||||
{-6,-11,1,17,-12,-4,-7,14,-21},
|
||||
{18,-31,34,-22,17,-19,20,24,6},
|
||||
{33,-18,17,-15,31,-5,3,27,-3},
|
||||
{-18,-20,-18,31,6,4,-2,-12,24},
|
||||
{27,14,4,-29,-3,5,-29,8,-12},
|
||||
{-15,-7,-23,23,-9,-8,6,8,-12},
|
||||
{33,-23,-19,-4,-8,-7,11,-12,31},
|
||||
{-20,19,-15,-30,11,32,7,14,-5},
|
||||
{-23,18,-32,-2,-31,-7,8,24,16},
|
||||
{32,-4,-10,-14,-6,-1,0,23,23},
|
||||
{25,0,-23,22,12,28,-27,15,4},
|
||||
{-30,-13,-16,-3,-3,-32,-3,27,-31},
|
||||
{22,1,26,4,-2,-13,26,17,14},
|
||||
{-9,-18,3,-20,-27,-32,-11,27,13},
|
||||
{-17,33,-7,19,-32,13,-31,-2,-24},
|
||||
{-31,27,-31,-29,15,2,29,-15,33},
|
||||
{-18,-23,15,28,0,30,-4,12,-32},
|
||||
{-3,34,27,-25,-18,26,1,34,26},
|
||||
{-21,-31,-10,-13,-30,-17,-12,-26,31},
|
||||
{23,-31,-19,21,-17,-10,2,-23,23},
|
||||
{-3,6,0,-3,-32,0,-10,-25,14},
|
||||
{-19,9,14,-27,20,15,-5,-27,18},
|
||||
{11,-6,24,7,-17,26,20,-31,-25},
|
||||
{-25,4,-16,30,33,23,-4,-4,23}
|
||||
};
|
||||
|
||||
|
||||
IEnumerable<int> ROWS = Enumerable.Range(0, rows);
|
||||
IEnumerable<int> COLS = Enumerable.Range(0, cols);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(rows, cols, -100, 100, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
int[] signs_domain = {-1,1};
|
||||
// This don't work at the moment...
|
||||
IntVar[] row_signs = solver.MakeIntVarArray(rows, signs_domain, "row_signs");
|
||||
IntVar[] col_signs = solver.MakeIntVarArray(cols, signs_domain, "col_signs");
|
||||
|
||||
|
||||
|
||||
// To optimize
|
||||
IntVar total_sum = x_flat.Sum().VarWithName("total_sum");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
foreach(int i in ROWS) {
|
||||
foreach(int j in COLS) {
|
||||
solver.Add(x[i,j] == data[i,j] * row_signs[i] * col_signs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
// row sums
|
||||
IntVar[] row_sums = (from i in ROWS
|
||||
select (from j in COLS
|
||||
select x[i,j]
|
||||
).ToArray().Sum().Var()).ToArray();
|
||||
|
||||
foreach(int i in ROWS) {
|
||||
row_sums[i].SetMin(0);
|
||||
}
|
||||
|
||||
// col sums
|
||||
IntVar[] col_sums = (from j in COLS
|
||||
select (from i in ROWS
|
||||
select x[i,j]
|
||||
).ToArray().Sum().Var()).ToArray();
|
||||
|
||||
foreach(int j in COLS) {
|
||||
col_sums[j].SetMin(0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = total_sum.Minimize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(col_signs.Concat(row_signs).ToArray(),
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("Sum: {0}",total_sum.Value());
|
||||
Console.Write("row_sums: ");
|
||||
foreach(int i in ROWS) {
|
||||
Console.Write(row_sums[i].Value() + " ");
|
||||
}
|
||||
Console.Write("\nrow_signs: ");
|
||||
foreach(int i in ROWS) {
|
||||
Console.Write(row_signs[i].Value() + " ");
|
||||
}
|
||||
|
||||
Console.Write("\ncol_sums: ");
|
||||
foreach(int j in COLS) {
|
||||
Console.Write(col_sums[j].Value() + " ");
|
||||
}
|
||||
Console.Write("\ncol_signs: ");
|
||||
foreach(int j in COLS) {
|
||||
Console.Write(col_signs[j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
foreach(int i in ROWS) {
|
||||
foreach(int j in COLS) {
|
||||
Console.Write("{0,3} ", x[i,j].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
112
examples/dotnet/csharp/eq10.cs
Normal file
112
examples/dotnet/csharp/eq10.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Eq10
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Eq 10 in Google CP Solver.
|
||||
*
|
||||
* Standard benchmark problem.
|
||||
*
|
||||
* Also see http://hakank.org/or-tools/eq10.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Eq10");
|
||||
|
||||
int n = 7;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar X1 = solver.MakeIntVar(0, 10, "X1");
|
||||
IntVar X2 = solver.MakeIntVar(0, 10, "X2");
|
||||
IntVar X3 = solver.MakeIntVar(0, 10, "X3");
|
||||
IntVar X4 = solver.MakeIntVar(0, 10, "X4");
|
||||
IntVar X5 = solver.MakeIntVar(0, 10, "X5");
|
||||
IntVar X6 = solver.MakeIntVar(0, 10, "X6");
|
||||
IntVar X7 = solver.MakeIntVar(0, 10, "X7");
|
||||
|
||||
IntVar[] X = {X1,X2,X3,X4,X5,X6,X7};
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(0+98527*X1+34588*X2+5872*X3+59422*X5+65159*X7
|
||||
== 1547604+30704*X4+29649*X6);
|
||||
|
||||
solver.Add(0+98957*X2+83634*X3+69966*X4+62038*X5+37164*X6+85413*X7
|
||||
== 1823553+93989*X1);
|
||||
|
||||
solver.Add(900032+10949*X1+77761*X2+67052*X5
|
||||
== 0+80197*X3+61944*X4+92964*X6+44550*X7);
|
||||
|
||||
solver.Add(0+73947*X1+84391*X3+81310*X5
|
||||
== 1164380+96253*X2+44247*X4+70582*X6+33054*X7);
|
||||
|
||||
solver.Add(0+13057*X3+42253*X4+77527*X5+96552*X7
|
||||
== 1185471+60152*X1+21103*X2+97932*X6);
|
||||
|
||||
solver.Add(1394152+66920*X1+55679*X4
|
||||
== 0+64234*X2+65337*X3+45581*X5+67707*X6+98038*X7);
|
||||
|
||||
solver.Add(0+68550*X1+27886*X2+31716*X3+73597*X4+38835*X7
|
||||
== 279091+88963*X5+76391*X6);
|
||||
|
||||
solver.Add(0+76132*X2+71860*X3+22770*X4+68211*X5+78587*X6
|
||||
== 480923+48224*X1+82817*X7);
|
||||
|
||||
solver.Add(519878+94198*X2+87234*X3+37498*X4
|
||||
== 0+71583*X1+25728*X5+25495*X6+70023*X7);
|
||||
|
||||
solver.Add(361921+78693*X1+38592*X5+38478*X6
|
||||
== 0+94129*X2+43188*X3+82528*X4+69025*X7);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(X,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(X[i].ToString() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
124
examples/dotnet/csharp/eq20.cs
Normal file
124
examples/dotnet/csharp/eq20.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Eq20
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Eq 20 in Google CP Solver.
|
||||
*
|
||||
* Standard benchmark problem.
|
||||
*
|
||||
* Also see http://hakank.org/or-tools/eq20.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Eq20");
|
||||
|
||||
int n = 7;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar X0 = solver.MakeIntVar(0, 10, "X0");
|
||||
IntVar X1 = solver.MakeIntVar(0, 10, "X1");
|
||||
IntVar X2 = solver.MakeIntVar(0, 10, "X2");
|
||||
IntVar X3 = solver.MakeIntVar(0, 10, "X3");
|
||||
IntVar X4 = solver.MakeIntVar(0, 10, "X4");
|
||||
IntVar X5 = solver.MakeIntVar(0, 10, "X5");
|
||||
IntVar X6 = solver.MakeIntVar(0, 10, "X6");
|
||||
|
||||
IntVar[] X = {X0,X1,X2,X3,X4,X5,X6};
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(-76706*X0 + 98205*X1 + 23445*X2 + 67921*X3 + 24111*X4 +
|
||||
-48614*X5 + -41906*X6 == 821228);
|
||||
solver.Add(87059*X0 + -29101*X1 + -5513*X2 + -21219*X3 + 22128*X4 +
|
||||
7276*X5 + 57308*X6 == 22167);
|
||||
solver.Add(-60113*X0 + 29475*X1 + 34421*X2 + -76870*X3 + 62646*X4 +
|
||||
29278*X5 + -15212*X6 == 251591);
|
||||
solver.Add(49149*X0 + 52871*X1 + -7132*X2 + 56728*X3 + -33576*X4 +
|
||||
-49530*X5 + -62089*X6 == 146074);
|
||||
solver.Add(-10343*X0 + 87758*X1 + -11782*X2 + 19346*X3 + 70072*X4 +
|
||||
-36991*X5 + 44529*X6 == 740061);
|
||||
solver.Add(85176*X0 + -95332*X1 + -1268*X2 + 57898*X3 + 15883*X4 +
|
||||
50547*X5 + 83287*X6 == 373854);
|
||||
solver.Add(-85698*X0 + 29958*X1 + 57308*X2 + 48789*X3 + -78219*X4 +
|
||||
4657*X5 + 34539*X6 == 249912);
|
||||
solver.Add(-67456*X0 + 84750*X1 + -51553*X2 + 21239*X3 + 81675*X4 +
|
||||
-99395*X5 + -4254*X6 == 277271);
|
||||
solver.Add(94016*X0 + -82071*X1 + 35961*X2 + 66597*X3 + -30705*X4 +
|
||||
-44404*X5 + -38304*X6 == 25334);
|
||||
solver.Add(-60301*X0 + 31227*X1 + 93951*X2 + 73889*X3 + 81526*X4 +
|
||||
-72702*X5 + 68026*X6 == 1410723);
|
||||
solver.Add(-16835*X0 + 47385*X1 + 97715*X2 + -12640*X3 + 69028*X4 +
|
||||
76212*X5 + -81102*X6 == 1244857);
|
||||
solver.Add(-43277*X0 + 43525*X1 + 92298*X2 + 58630*X3 + 92590*X4 +
|
||||
-9372*X5 + -60227*X6 == 1503588);
|
||||
solver.Add(-64919*X0 + 80460*X1 + 90840*X2 + -59624*X3 + -75542*X4 +
|
||||
25145*X5 + -47935*X6 == 18465);
|
||||
solver.Add(-45086*X0 + 51830*X1 + -4578*X2 + 96120*X3 + 21231*X4 +
|
||||
97919*X5 + 65651*X6 == 1198280);
|
||||
solver.Add(85268*X0 + 54180*X1 + -18810*X2 + -48219*X3 + 6013*X4 +
|
||||
78169*X5 + -79785*X6 == 90614);
|
||||
solver.Add(8874*X0 + -58412*X1 + 73947*X2 + 17147*X3 + 62335*X4 +
|
||||
16005*X5 + 8632*X6 == 752447);
|
||||
solver.Add(71202*X0 + -11119*X1 + 73017*X2 + -38875*X3 + -14413*X4 +
|
||||
-29234*X5 + 72370*X6 == 129768);
|
||||
solver.Add(1671*X0 + -34121*X1 + 10763*X2 + 80609*X3 + 42532*X4 +
|
||||
93520*X5 + -33488*X6 == 915683);
|
||||
solver.Add(51637*X0 + 67761*X1 + 95951*X2 + 3834*X3 + -96722*X4 +
|
||||
59190*X5 + 15280*X6 == 533909);
|
||||
solver.Add(-16105*X0 + 62397*X1 + -6704*X2 + 43340*X3 + 95100*X4 +
|
||||
-68610*X5 + 58301*X6 == 876370);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(X,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(X[i].ToString() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
15
examples/dotnet/csharp/examples.csproj
Normal file
15
examples/dotnet/csharp/examples.csproj
Normal file
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<GenerateTailCalls>true</GenerateTailCalls>
|
||||
<StartupObject>APuzzle.Main</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
248
examples/dotnet/csharp/fill_a_pix.cs
Normal file
248
examples/dotnet/csharp/fill_a_pix.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// 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 FillAPix
|
||||
{
|
||||
|
||||
static int X = -1;
|
||||
|
||||
//
|
||||
// Default problem.
|
||||
// Puzzle 1 from
|
||||
// http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules
|
||||
|
||||
//
|
||||
static int default_n = 10;
|
||||
static int[,] default_puzzle = {{X,X,X,X,X,X,X,X,0,X},
|
||||
{X,8,8,X,2,X,0,X,X,X},
|
||||
{5,X,8,X,X,X,X,X,X,X},
|
||||
{X,X,X,X,X,2,X,X,X,2},
|
||||
{1,X,X,X,4,5,6,X,X,X},
|
||||
{X,0,X,X,X,7,9,X,X,6},
|
||||
{X,X,X,6,X,X,9,X,X,6},
|
||||
{X,X,6,6,8,7,8,7,X,5},
|
||||
{X,4,X,6,6,6,X,6,X,4},
|
||||
{X,X,X,X,X,X,3,X,X,X}};
|
||||
|
||||
// for the actual problem
|
||||
static int n;
|
||||
static int[,] puzzle;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Fill-a-Pix problem
|
||||
*
|
||||
* From http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/basiclogic
|
||||
* """
|
||||
* Each puzzle consists of a grid containing clues in various places. The
|
||||
* object is to reveal a hidden picture by painting the squares around each
|
||||
* clue so that the number of painted squares, including the square with
|
||||
* the clue, matches the value of the clue.
|
||||
* """
|
||||
*
|
||||
* http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/rules
|
||||
* """
|
||||
* Fill-a-Pix is a Minesweeper-like puzzle based on a grid with a pixilated
|
||||
* picture hidden inside. Using logic alone, the solver determines which
|
||||
* squares are painted and which should remain empty until the hidden picture
|
||||
* is completely exposed.
|
||||
* """
|
||||
*
|
||||
* Fill-a-pix History:
|
||||
* http://www.conceptispuzzles.com/index.aspx?uri=puzzle/fill-a-pix/history
|
||||
*
|
||||
* Also see http://www.hakank.org/google_or_tools/fill_a_pix.py
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("FillAPix");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int[] S = {-1, 0, 1};
|
||||
|
||||
Console.WriteLine("Problem:");
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (puzzle[i,j] > X) {
|
||||
Console.Write(puzzle[i,j] + " ");
|
||||
} else {
|
||||
Console.Write("X ");
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] pict = solver.MakeIntVarMatrix(n, n, 0, 1, "pict");
|
||||
IntVar[] pict_flat = pict.Flatten(); // for branching
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (puzzle[i,j] > X) {
|
||||
|
||||
// this cell is the sum of all surrounding cells
|
||||
var tmp = from a in S from b in S where
|
||||
i + a >= 0 &&
|
||||
j + b >= 0 &&
|
||||
i + a < n &&
|
||||
j + b < n
|
||||
select(pict[i+a,j+b]);
|
||||
|
||||
solver.Add(tmp.ToArray().Sum() == puzzle[i,j]);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(pict_flat,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int sol = 0;
|
||||
while (solver.NextSolution()) {
|
||||
sol++;
|
||||
Console.WriteLine("Solution #{0} ", sol + " ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++){
|
||||
Console.Write(pict[i,j].Value() == 1 ? "#" : " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Reads a Fill-a-Pix file.
|
||||
* File format:
|
||||
* # a comment which is ignored
|
||||
* % a comment which also is ignored
|
||||
* number of rows and columns (n x n)
|
||||
* <
|
||||
* row number of neighbours lines...
|
||||
* >
|
||||
*
|
||||
* 0..8 means number of neighbours, "." mean unknown (may be a mine)
|
||||
*
|
||||
* Example (from fill_a_pix1.txt):
|
||||
*
|
||||
* 10
|
||||
* ........0.
|
||||
* .88.2.0...
|
||||
* 5.8.......
|
||||
* .....2...2
|
||||
* 1...456...
|
||||
* .0...79..6
|
||||
* ...6..9..6
|
||||
* ..668787.5
|
||||
* .4.666.6.4
|
||||
* ......3...
|
||||
*
|
||||
*/
|
||||
private static void readFile(String file) {
|
||||
|
||||
Console.WriteLine("readFile(" + file + ")");
|
||||
int lineCount = 0;
|
||||
|
||||
TextReader inr = new StreamReader(file);
|
||||
String str;
|
||||
while ((str = inr.ReadLine()) != null && str.Length > 0) {
|
||||
|
||||
str = str.Trim();
|
||||
|
||||
// ignore comments
|
||||
if(str.StartsWith("#") || str.StartsWith("%")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine(str);
|
||||
if (lineCount == 0) {
|
||||
n = Convert.ToInt32(str); // number of rows
|
||||
puzzle = new int[n,n];
|
||||
} else {
|
||||
// the problem matrix
|
||||
String[] row = Regex.Split(str, "");
|
||||
for(int j = 1; j <= n; j++) {
|
||||
String s = row[j];
|
||||
if (s.Equals(".")) {
|
||||
puzzle[lineCount-1, j-1] = -1;
|
||||
} else {
|
||||
puzzle[lineCount-1, j-1] = Convert.ToInt32(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lineCount++;
|
||||
|
||||
} // end while
|
||||
|
||||
inr.Close();
|
||||
|
||||
} // end readFile
|
||||
|
||||
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
String file = "";
|
||||
if (args.Length > 0) {
|
||||
file = args[0];
|
||||
readFile(file);
|
||||
} else {
|
||||
puzzle = default_puzzle;
|
||||
n = default_n;
|
||||
}
|
||||
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
180
examples/dotnet/csharp/furniture_moving.cs
Normal file
180
examples/dotnet/csharp/furniture_moving.cs
Normal file
@@ -0,0 +1,180 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class FurnitureMoving
|
||||
{
|
||||
|
||||
/*
|
||||
* Decompositon of cumulative.
|
||||
*
|
||||
* Inspired by the MiniZinc implementation:
|
||||
* http://www.g12.csse.unimelb.edu.au/wiki/doku.php?id=g12:zinc:lib:minizinc:std:cumulative.mzn&s[]=cumulative
|
||||
* The MiniZinc decomposition is discussed in the paper:
|
||||
* A. Schutt, T. Feydy, P.J. Stuckey, and M. G. Wallace.
|
||||
* "Why cumulative decomposition is not as bad as it sounds."
|
||||
* Download:
|
||||
* http://www.cs.mu.oz.au/%7Epjs/rcpsp/papers/cp09-cu.pdf
|
||||
* http://www.cs.mu.oz.au/%7Epjs/rcpsp/cumu_lazyfd.pdf
|
||||
*
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* s: start_times assumption: IntVar[]
|
||||
* d: durations assumption: int[]
|
||||
* r: resources assumption: int[]
|
||||
* b: resource limit assumption: IntVar or int
|
||||
*
|
||||
*
|
||||
*/
|
||||
static void MyCumulative(Solver solver,
|
||||
IntVar[] s,
|
||||
int[] d,
|
||||
int[] r,
|
||||
IntVar b) {
|
||||
|
||||
int[] tasks = (from i in Enumerable.Range(0, s.Length)
|
||||
where r[i] > 0 && d[i] > 0
|
||||
select i).ToArray();
|
||||
int times_min = tasks.Min(i => (int)s[i].Min());
|
||||
int d_max = d.Max();
|
||||
int times_max = tasks.Max(i => (int)s[i].Max() + d_max);
|
||||
for(int t = times_min; t <= times_max; t++) {
|
||||
ArrayList bb = new ArrayList();
|
||||
foreach(int i in tasks) {
|
||||
bb.Add(((s[i] <= t) * (s[i] + d[i]> t) * r[i]).Var());
|
||||
}
|
||||
solver.Add((bb.ToArray(typeof(IntVar)) as IntVar[]).Sum() <= b);
|
||||
}
|
||||
|
||||
// Somewhat experimental:
|
||||
// This constraint is needed to constrain the upper limit of b.
|
||||
if (b is IntVar) {
|
||||
solver.Add(b <= r.Sum());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Moving furnitures (scheduling) problem in Google CP Solver.
|
||||
*
|
||||
* Marriott & Stukey: 'Programming with constraints', page 112f
|
||||
*
|
||||
* The model implements an decomposition of the global constraint
|
||||
* cumulative (see above).
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/furniture_moving.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("FurnitureMoving");
|
||||
|
||||
int n = 4;
|
||||
int[] duration = {30,10,15,15};
|
||||
int[] demand = { 3, 1, 3, 2};
|
||||
int upper_limit = 160;
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] start_times = solver.MakeIntVarArray(n, 0, upper_limit, "start_times");
|
||||
IntVar[] end_times = solver.MakeIntVarArray(n, 0, upper_limit * 2, "end_times");
|
||||
IntVar end_time = solver.MakeIntVar(0, upper_limit * 2, "end_time");
|
||||
|
||||
// number of needed resources, to be minimized or constrained
|
||||
IntVar num_resources = solver.MakeIntVar(0, 10, "num_resources");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add(end_times[i] == start_times[i] + duration[i]);
|
||||
}
|
||||
|
||||
solver.Add(end_time == end_times.Max());
|
||||
MyCumulative(solver, start_times, duration, demand, num_resources);
|
||||
|
||||
|
||||
//
|
||||
// Some extra constraints to play with
|
||||
//
|
||||
|
||||
// all tasks must end within an hour
|
||||
// solver.Add(end_time <= 60);
|
||||
|
||||
// All tasks should start at time 0
|
||||
// for(int i = 0; i < n; i++) {
|
||||
// solver.Add(start_times[i] == 0);
|
||||
// }
|
||||
|
||||
|
||||
// limitation of the number of people
|
||||
// solver.Add(num_resources <= 3);
|
||||
solver.Add(num_resources <= 4);
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
|
||||
// OptimizeVar obj = num_resources.Minimize(1);
|
||||
OptimizeVar obj = end_time.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(start_times,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("num_resources: {0} end_time: {1}",
|
||||
num_resources.Value(), end_time.Value());
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.WriteLine("Task {0,1}: {1,2} -> {2,2} -> {3,2} (demand: {4})",
|
||||
i,
|
||||
start_times[i].Value(),
|
||||
duration[i],
|
||||
end_times[i].Value(),
|
||||
demand[i]);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
150
examples/dotnet/csharp/furniture_moving_intervals.cs
Normal file
150
examples/dotnet/csharp/furniture_moving_intervals.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class FurnitureMovingIntervals
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Moving furnitures (scheduling) problem in Google CP Solver.
|
||||
*
|
||||
* Marriott & Stukey: 'Programming with constraints', page 112f
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/furniture_moving.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("FurnitureMovingIntervals");
|
||||
|
||||
const int n = 4;
|
||||
int[] durations = {30,10,15,15};
|
||||
int[] demand = {3, 1, 3, 2};
|
||||
const int upper_limit = 160;
|
||||
const int max_num_workers = 5;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntervalVar[] tasks = new IntervalVar[n];
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
tasks[i] = solver.MakeFixedDurationIntervalVar(0,
|
||||
upper_limit - durations[i],
|
||||
durations[i],
|
||||
false,
|
||||
"task_" + i);
|
||||
}
|
||||
|
||||
// Fillers that span the whole resource and limit the available
|
||||
// number of workers.
|
||||
IntervalVar[] fillers = new IntervalVar[max_num_workers];
|
||||
for (int i = 0; i < max_num_workers; ++i)
|
||||
{
|
||||
fillers[i] = solver.MakeFixedDurationIntervalVar(0,
|
||||
0,
|
||||
upper_limit,
|
||||
true,
|
||||
"filler_" + i);
|
||||
}
|
||||
|
||||
// Number of needed resources, to be minimized or constrained.
|
||||
IntVar num_workers = solver.MakeIntVar(0, max_num_workers, "num_workers");
|
||||
// Links fillers and num_workers.
|
||||
for (int i = 0; i < max_num_workers; ++i)
|
||||
{
|
||||
solver.Add((num_workers > i) + fillers[i].PerformedExpr() == 1);
|
||||
}
|
||||
|
||||
// Creates makespan.
|
||||
IntVar[] ends = new IntVar[n];
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
ends[i] = tasks[i].EndExpr().Var();
|
||||
}
|
||||
IntVar end_time = ends.Max().VarWithName("end_time");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
IntervalVar[] all_tasks = new IntervalVar[n + max_num_workers];
|
||||
int[] all_demands = new int[n + max_num_workers];
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
all_tasks[i] = tasks[i];
|
||||
all_demands[i] = demand[i];
|
||||
}
|
||||
for (int i = 0; i < max_num_workers; ++i)
|
||||
{
|
||||
all_tasks[i + n] = fillers[i];
|
||||
all_demands[i + n] = 1;
|
||||
}
|
||||
solver.Add(all_tasks.Cumulative(all_demands, max_num_workers, "workers"));
|
||||
|
||||
//
|
||||
// Some extra constraints to play with
|
||||
//
|
||||
|
||||
// all tasks must end within an hour
|
||||
// solver.Add(end_time <= 60);
|
||||
|
||||
// All tasks should start at time 0
|
||||
// for(int i = 0; i < n; i++) {
|
||||
// solver.Add(tasks[i].StartAt(0));
|
||||
// }
|
||||
|
||||
|
||||
// limitation of the number of people
|
||||
// solver.Add(num_workers <= 3);
|
||||
solver.Add(num_workers <= 4);
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
|
||||
// OptimizeVar obj = num_workers.Minimize(1);
|
||||
OptimizeVar obj = end_time.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all_tasks, Solver.INTERVAL_DEFAULT);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine(num_workers.ToString() + ", " + end_time.ToString());
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.WriteLine("{0} (demand:{1})", tasks[i].ToString(), demand[i]);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("Solutions: {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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
200
examples/dotnet/csharp/futoshiki.cs
Normal file
200
examples/dotnet/csharp/futoshiki.cs
Normal file
@@ -0,0 +1,200 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class Futoshiki
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Futoshiki problem.
|
||||
*
|
||||
* From http://en.wikipedia.org/wiki/Futoshiki
|
||||
* """
|
||||
* The puzzle is played on a square grid, such as 5 x 5. The objective
|
||||
* is to place the numbers 1 to 5 (or whatever the dimensions are)
|
||||
* such that each row, and column contains each of the digits 1 to 5.
|
||||
* Some digits may be given at the start. In addition, inequality
|
||||
* constraints are also initially specifed between some of the squares,
|
||||
* such that one must be higher or lower than its neighbour. These
|
||||
* constraints must be honoured as the grid is filled out.
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/futoshiki.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int[,] values, int[,] lt)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Futoshiki");
|
||||
|
||||
int size = values.GetLength(0);
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, size);
|
||||
IEnumerable<int> NUMQD = Enumerable.Range(0, lt.GetLength(0));
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] field = solver.MakeIntVarMatrix(size, size, 1, size, "field");
|
||||
IntVar[] field_flat = field.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
|
||||
// set initial values
|
||||
foreach(int row in RANGE) {
|
||||
foreach(int col in RANGE) {
|
||||
if (values[row,col] > 0) {
|
||||
solver.Add(field[row,col] == values[row,col]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// all rows have to be different
|
||||
foreach(int row in RANGE) {
|
||||
solver.Add((from col in RANGE
|
||||
select field[row,col]).ToArray().AllDifferent());
|
||||
}
|
||||
|
||||
|
||||
// all columns have to be different
|
||||
foreach(int col in RANGE) {
|
||||
solver.Add((from row in RANGE
|
||||
select field[row,col]).ToArray().AllDifferent());
|
||||
}
|
||||
|
||||
|
||||
// all < constraints are satisfied
|
||||
// Also: make 0-based
|
||||
foreach(int i in NUMQD) {
|
||||
solver.Add(field[ lt[i,0]-1, lt[i,1]-1 ] <
|
||||
field[ lt[i,2]-1, lt[i,3]-1 ] );
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(field_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
foreach(int i in RANGE) {
|
||||
foreach(int j in RANGE) {
|
||||
Console.Write("{0} ", field[i,j].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
//
|
||||
// Example from Tailor model futoshiki.param/futoshiki.param
|
||||
// Solution:
|
||||
// 5 1 3 2 4
|
||||
// 1 4 2 5 3
|
||||
// 2 3 1 4 5
|
||||
// 3 5 4 1 2
|
||||
// 4 2 5 3 1
|
||||
//
|
||||
// Futoshiki instance, by Andras Salamon
|
||||
// specify the numbers in the grid
|
||||
//
|
||||
int[,] values1 = {
|
||||
{0, 0, 3, 2, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0},
|
||||
{0, 0, 0, 0, 0}};
|
||||
|
||||
|
||||
// [i1,j1, i2,j2] requires that values[i1,j1] < values[i2,j2]
|
||||
// Note: 1-based
|
||||
int [,] lt1 = {
|
||||
{1,2, 1,1},
|
||||
{1,4, 1,5},
|
||||
{2,3, 1,3},
|
||||
{3,3, 2,3},
|
||||
{3,4, 2,4},
|
||||
{2,5, 3,5},
|
||||
{3,2, 4,2},
|
||||
{4,4, 4,3},
|
||||
{5,2, 5,1},
|
||||
{5,4, 5,3},
|
||||
{5,5, 4,5}};
|
||||
|
||||
|
||||
//
|
||||
// Example from http://en.wikipedia.org/wiki/Futoshiki
|
||||
// Solution:
|
||||
// 5 4 3 2 1
|
||||
// 4 3 1 5 2
|
||||
// 2 1 4 3 5
|
||||
// 3 5 2 1 4
|
||||
// 1 2 5 4 3
|
||||
//
|
||||
int[,] values2 = {
|
||||
{0, 0, 0, 0, 0},
|
||||
{4, 0, 0, 0, 2},
|
||||
{0, 0, 4, 0, 0},
|
||||
{0, 0, 0, 0, 4},
|
||||
{0, 0, 0, 0, 0}};
|
||||
|
||||
// Note: 1-based
|
||||
int[,] lt2 = {
|
||||
{1,2, 1,1},
|
||||
{1,4, 1,3},
|
||||
{1,5, 1,4},
|
||||
{4,4, 4,5},
|
||||
{5,1, 5,2},
|
||||
{5,2, 5,3}
|
||||
};
|
||||
|
||||
Console.WriteLine("Problem 1");
|
||||
Solve(values1, lt1);
|
||||
|
||||
Console.WriteLine("\nProblem 2");
|
||||
Solve(values2, lt2);
|
||||
|
||||
}
|
||||
}
|
||||
154
examples/dotnet/csharp/gate_scheduling_sat.cs
Normal file
154
examples/dotnet/csharp/gate_scheduling_sat.cs
Normal file
@@ -0,0 +1,154 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.
|
||||
|
||||
// Gate Scheduling problem.
|
||||
//
|
||||
// We have a set of jobs to perform (duration, width).
|
||||
// We have two parallel machines that can perform this job.
|
||||
// One machine can only perform one job at a time.
|
||||
// At any point in time, the sum of the width of the two active jobs does not
|
||||
// exceed a max_length.
|
||||
//
|
||||
//The objective is to minimize the max end time of all jobs.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.Sat;
|
||||
|
||||
public class GateSchedulingSat
|
||||
{
|
||||
static void Solve()
|
||||
{
|
||||
CpModel model = new CpModel();
|
||||
|
||||
int[,] jobs = new [,] {{3, 3},
|
||||
{2, 5},
|
||||
{1, 3},
|
||||
{3, 7},
|
||||
{7, 3},
|
||||
{2, 2},
|
||||
{2, 2},
|
||||
{5, 5},
|
||||
{10, 2},
|
||||
{4, 3},
|
||||
{2, 6},
|
||||
{1, 2},
|
||||
{6, 8},
|
||||
{4, 5},
|
||||
{3, 7}};
|
||||
|
||||
int max_length = 10;
|
||||
int num_jobs = jobs.GetLength(0);
|
||||
var all_jobs = Enumerable.Range(0, num_jobs);
|
||||
|
||||
int horizon = 0;
|
||||
foreach (int j in all_jobs)
|
||||
{
|
||||
horizon += jobs[j, 0];
|
||||
}
|
||||
|
||||
|
||||
List<IntervalVar> intervals = new List<IntervalVar>();
|
||||
List<IntervalVar> intervals0 = new List<IntervalVar>();
|
||||
List<IntervalVar> intervals1 = new List<IntervalVar>();
|
||||
List<IntVar> performed = new List<IntVar>();
|
||||
List<IntVar> starts = new List<IntVar>();
|
||||
List<IntVar> ends = new List<IntVar>();
|
||||
List<int> demands = new List<int>();
|
||||
|
||||
foreach (int i in all_jobs)
|
||||
{
|
||||
// Create main interval.
|
||||
IntVar start = model.NewIntVar(0, horizon, String.Format("start_{0}", i));
|
||||
int duration = jobs[i, 0];
|
||||
IntVar end = model.NewIntVar(0, horizon, String.Format("end_{0}", i));
|
||||
IntervalVar interval = model.NewIntervalVar(
|
||||
start, duration, end, String.Format("interval_{0}", i));
|
||||
starts.Add(start);
|
||||
intervals.Add(interval);
|
||||
ends.Add(end);
|
||||
demands.Add(jobs[i, 1]);
|
||||
|
||||
IntVar performed_on_m0 =
|
||||
model.NewBoolVar(String.Format("perform_{0}_on_m0", i));
|
||||
performed.Add(performed_on_m0);
|
||||
|
||||
// Create an optional copy of interval to be executed on machine 0.
|
||||
IntVar start0 = model.NewOptionalIntVar(
|
||||
0, horizon, performed_on_m0, String.Format("start_{0}_on_m0", i));
|
||||
IntVar end0 = model.NewOptionalIntVar(
|
||||
0, horizon, performed_on_m0, String.Format("end_{0}_on_m0", i));
|
||||
IntervalVar interval0 = model.NewOptionalIntervalVar(
|
||||
start0, duration, end0, performed_on_m0,
|
||||
String.Format("interval_{0}_on_m0", i));
|
||||
intervals0.Add(interval0);
|
||||
|
||||
// Create an optional copy of interval to be executed on machine 1.
|
||||
IntVar start1 = model.NewOptionalIntVar(
|
||||
0, horizon, performed_on_m0.Not(),
|
||||
String.Format("start_{0}_on_m1", i));
|
||||
IntVar end1 = model.NewOptionalIntVar(0, horizon, performed_on_m0.Not(),
|
||||
String.Format("end_{0}_on_m1", i));
|
||||
IntervalVar interval1 = model.NewOptionalIntervalVar(
|
||||
start1, duration, end1, performed_on_m0.Not(),
|
||||
String.Format("interval_{0}_on_m1", i));
|
||||
intervals1.Add(interval1);
|
||||
|
||||
// We only propagate the constraint if the tasks is performed on the
|
||||
// machine.
|
||||
model.Add(start0 == start).OnlyEnforceIf(performed_on_m0);
|
||||
model.Add(start1 == start).OnlyEnforceIf(performed_on_m0.Not());
|
||||
}
|
||||
|
||||
// Max Length constraint (modeled as a cumulative)
|
||||
model.AddCumulative(intervals, demands, max_length);
|
||||
|
||||
// Choose which machine to perform the jobs on.
|
||||
model.AddNoOverlap(intervals0);
|
||||
model.AddNoOverlap(intervals1);
|
||||
|
||||
// Objective variable.
|
||||
IntVar makespan = model.NewIntVar(0, horizon, "makespan");
|
||||
model.AddMaxEquality(makespan, ends);
|
||||
model.Minimize(makespan);
|
||||
|
||||
// Symmetry breaking.
|
||||
model.Add(performed[0] == 0);
|
||||
|
||||
// Creates the solver and solve.
|
||||
CpSolver solver = new CpSolver();
|
||||
solver.Solve(model);
|
||||
|
||||
|
||||
// Output solution.
|
||||
Console.WriteLine("Solution");
|
||||
Console.WriteLine(" - makespan = " + solver.ObjectiveValue);
|
||||
foreach (int i in all_jobs)
|
||||
{
|
||||
long performed_machine = 1 - solver.Value(performed[i]);
|
||||
long start = solver.Value(starts[i]);
|
||||
Console.WriteLine(
|
||||
String.Format(" - Job {0} starts at {1} on machine {2}",
|
||||
i, start, performed_machine));
|
||||
}
|
||||
Console.WriteLine("Statistics");
|
||||
Console.WriteLine(" - conflicts : " + solver.NumConflicts());
|
||||
Console.WriteLine(" - branches : " + solver.NumBranches());
|
||||
Console.WriteLine(" - wall time : " + solver.WallTime() + " ms");
|
||||
}
|
||||
|
||||
static void Main() {
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
128
examples/dotnet/csharp/golomb_ruler.cs
Normal file
128
examples/dotnet/csharp/golomb_ruler.cs
Normal file
@@ -0,0 +1,128 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class GolombRuler
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Golomb Ruler problem.
|
||||
*
|
||||
* This C# implementation is based on Charles Prud'homme's
|
||||
* or-tools/Java model:
|
||||
* http://code.google.com/p/or-tools/source/browse/trunk/com/google/ortools/constraintsolver/samples/GolombRuler.java
|
||||
*
|
||||
*/
|
||||
private static void Solve(int m = 8)
|
||||
{
|
||||
Solver solver = new Solver("GolombRuler");
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] ticks = solver.MakeIntVarArray(m,
|
||||
0,
|
||||
((m < 31) ? (1 << (m + 1)) - 1 : 9999),
|
||||
"ticks");
|
||||
|
||||
IntVar[] diff = new IntVar[(m * m - m) / 2];
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(ticks[0] == 0);
|
||||
|
||||
for(int i = 0; i < ticks.Length - 1; i++) {
|
||||
solver.Add(ticks[i] < ticks[i+1]);
|
||||
}
|
||||
|
||||
|
||||
for (int k = 0, i = 0; i < m - 1; i++) {
|
||||
for (int j = i + 1; j < m; j++, k++) {
|
||||
diff[k] = (ticks[j]-ticks[i]).Var();
|
||||
solver.Add(diff[k] >= (j - i) * (j - i + 1) / 2);
|
||||
}
|
||||
}
|
||||
|
||||
solver.Add(diff.AllDifferent());
|
||||
|
||||
// break symetries
|
||||
if (m > 2) {
|
||||
solver.Add(diff[0] < diff[diff.Length - 1]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Optimization
|
||||
//
|
||||
OptimizeVar opt = ticks[m - 1].Minimize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(ticks,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
// We just want the debug info for larger instances.
|
||||
if (m >= 11) {
|
||||
|
||||
SearchMonitor log = solver.MakeSearchLog(10000, opt);
|
||||
solver.NewSearch(db, opt, log);
|
||||
|
||||
} else {
|
||||
|
||||
solver.NewSearch(db, opt);
|
||||
}
|
||||
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("opt: {0} [ ", ticks[m-1].Value());
|
||||
for(int i = 0; i < m; i++) {
|
||||
Console.Write("{0} ", ticks[i].Value());
|
||||
}
|
||||
Console.WriteLine("]");
|
||||
}
|
||||
|
||||
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 = 8;
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(n);
|
||||
}
|
||||
}
|
||||
112
examples/dotnet/csharp/grocery.cs
Normal file
112
examples/dotnet/csharp/grocery.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class Grocery
|
||||
{
|
||||
|
||||
public static void Decreasing(Solver solver, IntVar[] x) {
|
||||
for(int i = 0; i < x.Length - 1; i++) {
|
||||
solver.Add(x[i] <= x[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Simple decomposition of Prod() for an IntVar array
|
||||
//
|
||||
private static Constraint MyProd(IntVar[] x, int prod) {
|
||||
int len = x.Length;
|
||||
IntVar[] tmp = new IntVar[len];
|
||||
tmp[0] = x[0];
|
||||
for(int i = 1; i < len; i++) {
|
||||
tmp[i] = (tmp[i-1]*x[i]).Var();
|
||||
}
|
||||
|
||||
return tmp[len-1] == prod;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Grocery problem.
|
||||
*
|
||||
* From Christian Schulte, Gert Smolka, Finite Domain
|
||||
* http://www.mozart-oz.org/documentation/fdt/
|
||||
* Constraint Programming in Oz. A Tutorial. 2001.
|
||||
* """
|
||||
* A kid goes into a grocery store and buys four items. The cashier
|
||||
* charges $7.11, the kid pays and is about to leave when the cashier
|
||||
* calls the kid back, and says 'Hold on, I multiplied the four items
|
||||
* instead of adding them; I'll try again; Hah, with adding them the
|
||||
* price still comes to $7.11'. What were the prices of the four items?
|
||||
* """
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Grocery");
|
||||
|
||||
int n = 4;
|
||||
int c = 711;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
IntVar[] item = solver.MakeIntVarArray(n, 0, c / 2, "item");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(item.Sum() == c);
|
||||
// solver.Add(item[0] * item[1] * item[2] * item[3] == c * 100*100*100);
|
||||
// solver.Add(item.Prod() == c * 100*100*100);
|
||||
solver.Add(MyProd(item, c * 100*100*100));
|
||||
|
||||
|
||||
// Symmetry breaking
|
||||
Decreasing(solver, item);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(item,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(item[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
287
examples/dotnet/csharp/hidato_table.cs
Normal file
287
examples/dotnet/csharp/hidato_table.cs
Normal file
@@ -0,0 +1,287 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class HidatoTable
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
* Build closeness pairs for consecutive numbers.
|
||||
*
|
||||
* Build set of allowed pairs such that two consecutive numbers touch
|
||||
* each other in the grid.
|
||||
*
|
||||
* Returns:
|
||||
* A list of pairs for allowed consecutive position of numbers.
|
||||
*
|
||||
* Args:
|
||||
* rows: the number of rows in the grid
|
||||
* cols: the number of columns in the grid
|
||||
*/
|
||||
public static IntTupleSet BuildPairs(int rows, int cols)
|
||||
{
|
||||
int[] ix = {-1, 0, 1};
|
||||
var result_tmp = (from x in Enumerable.Range(0, rows)
|
||||
from y in Enumerable.Range(0, cols)
|
||||
from dx in ix
|
||||
from dy in ix
|
||||
where
|
||||
x + dx >= 0 &&
|
||||
x + dx < rows &&
|
||||
y + dy >= 0 &&
|
||||
y + dy < cols &&
|
||||
(dx != 0 || dy != 0)
|
||||
select new int[] {x * cols + y, (x + dx) * cols + (y + dy)}
|
||||
).ToArray();
|
||||
|
||||
// Convert to len x 2 matrix
|
||||
int len = result_tmp.Length;
|
||||
IntTupleSet result = new IntTupleSet(2);
|
||||
foreach(int[] r in result_tmp) {
|
||||
result.Insert(r);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Hidato puzzle in Google CP Solver.
|
||||
*
|
||||
* http://www.hidato.com/
|
||||
* """
|
||||
* Puzzles start semi-filled with numbered tiles.
|
||||
* The first and last numbers are circled.
|
||||
* Connect the numbers together to win. Consecutive
|
||||
* number must touch horizontally, vertically, or
|
||||
* diagonally.
|
||||
* """
|
||||
*
|
||||
* This is a port of the Python model hidato_table.py
|
||||
* made by Laurent Perron (using AllowedAssignments),
|
||||
* based on my (much slower) model hidato.py.
|
||||
*
|
||||
*/
|
||||
private static void Solve(int model = 1)
|
||||
{
|
||||
Solver solver = new Solver("HidatoTable");
|
||||
|
||||
//
|
||||
// models, a 0 indicates an open cell which number is not yet known.
|
||||
//
|
||||
|
||||
int[,] puzzle = null;
|
||||
if (model == 1) {
|
||||
|
||||
// Simple problem
|
||||
|
||||
// Solution 1:
|
||||
// 6 7 9
|
||||
// 5 2 8
|
||||
// 1 4 3
|
||||
int[,] puzzle1 = {{6, 0, 9},
|
||||
{0, 2, 8},
|
||||
{1, 0, 0}};
|
||||
puzzle = puzzle1;
|
||||
|
||||
} else if (model == 2) {
|
||||
|
||||
int[,] puzzle2 = {{0, 44, 41, 0, 0, 0, 0},
|
||||
{0, 43, 0, 28, 29, 0, 0},
|
||||
{0, 1, 0, 0, 0, 33, 0},
|
||||
{0, 2, 25, 4, 34, 0, 36},
|
||||
{49, 16, 0, 23, 0, 0, 0},
|
||||
{0, 19, 0, 0, 12, 7, 0},
|
||||
{0, 0, 0, 14, 0, 0, 0}};
|
||||
puzzle = puzzle2;
|
||||
|
||||
} else if (model == 3) {
|
||||
// Problems from the book:
|
||||
// Gyora Bededek: "Hidato: 2000 Pure Logic Puzzles"
|
||||
// Problem 1 (Practice)
|
||||
int[,] puzzle3 = {{0, 0, 20, 0, 0},
|
||||
{0, 0, 0, 16, 18},
|
||||
{22, 0, 15, 0, 0},
|
||||
{23, 0, 1, 14, 11},
|
||||
{0, 25, 0, 0, 12}};
|
||||
puzzle = puzzle3;
|
||||
|
||||
} else if (model == 4) {
|
||||
// problem 2 (Practice)
|
||||
int[,] puzzle4 = {{0, 0, 0, 0, 14},
|
||||
{0, 18, 12, 0, 0},
|
||||
{0, 0, 17, 4, 5},
|
||||
{0, 0, 7, 0, 0},
|
||||
{9, 8, 25, 1, 0}};
|
||||
puzzle = puzzle4;
|
||||
|
||||
} else if (model == 5) {
|
||||
// problem 3 (Beginner)
|
||||
int[,] puzzle5 = {{0, 26, 0, 0, 0, 18},
|
||||
{0, 0, 27, 0, 0, 19},
|
||||
{31, 23, 0, 0, 14, 0},
|
||||
{0, 33, 8, 0, 15, 1},
|
||||
{0, 0, 0, 5, 0, 0},
|
||||
{35, 36, 0, 10, 0, 0}};
|
||||
puzzle = puzzle5;
|
||||
|
||||
} else if (model == 6) {
|
||||
// Problem 15 (Intermediate)
|
||||
int[,] puzzle6 = {{64, 0, 0, 0, 0, 0, 0, 0},
|
||||
{1, 63, 0, 59, 15, 57, 53, 0},
|
||||
{0, 4, 0, 14, 0, 0, 0, 0},
|
||||
{3, 0, 11, 0, 20, 19, 0, 50},
|
||||
{0, 0, 0, 0, 22, 0, 48, 40},
|
||||
{9, 0, 0, 32, 23, 0, 0, 41},
|
||||
{27, 0, 0, 0, 36, 0, 46, 0},
|
||||
{28, 30, 0, 35, 0, 0, 0, 0}};
|
||||
puzzle = puzzle6;
|
||||
}
|
||||
|
||||
int r = puzzle.GetLength(0);
|
||||
int c = puzzle.GetLength(1);
|
||||
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("----- Solving problem {0} -----", model);
|
||||
Console.WriteLine();
|
||||
|
||||
PrintMatrix(puzzle);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] positions = solver.MakeIntVarArray(r*c, 0, r * c - 1, "p");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(positions.AllDifferent());
|
||||
|
||||
//
|
||||
// Fill in the clues
|
||||
//
|
||||
for(int i = 0; i < r; i++) {
|
||||
for(int j = 0; j < c; j++) {
|
||||
if (puzzle[i,j] > 0) {
|
||||
solver.Add(positions[puzzle[i,j] - 1] == i * c + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Consecutive numbers much touch each other in the grid.
|
||||
// We use an allowed assignment constraint to model it.
|
||||
IntTupleSet close_tuples = BuildPairs(r, c);
|
||||
for(int k = 1; k < r * c - 1; k++) {
|
||||
IntVar[] tmp = new IntVar[] {positions[k], positions[k + 1]};
|
||||
solver.Add(tmp.AllowedAssignments(close_tuples));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(positions,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int num_solution = 0;
|
||||
while (solver.NextSolution()) {
|
||||
num_solution++;
|
||||
PrintOneSolution(positions, r, c, num_solution);
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
// Print the current solution
|
||||
public static void PrintOneSolution(IntVar[] positions,
|
||||
int rows,
|
||||
int cols,
|
||||
int num_solution)
|
||||
{
|
||||
|
||||
Console.WriteLine("Solution {0}", num_solution);
|
||||
|
||||
// Create empty board
|
||||
int[,] board = new int[rows, cols];
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
board[i,j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill board with solution value
|
||||
for(int k = 0; k < rows*cols; k++) {
|
||||
int position = (int)positions[k].Value();
|
||||
board[position / cols, position % cols] = k + 1;
|
||||
}
|
||||
|
||||
PrintMatrix(board);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Pretty print of the matrix
|
||||
public static void PrintMatrix(int[,] game)
|
||||
{
|
||||
int rows = game.GetLength(0);
|
||||
int cols = game.GetLength(1);
|
||||
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
if (game[i,j] == 0) {
|
||||
Console.Write(" .");
|
||||
} else {
|
||||
Console.Write(" {0,2}", game[i,j] );
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
int model = 1;
|
||||
if (args.Length > 0) {
|
||||
|
||||
model = Convert.ToInt32(args[0]);
|
||||
Solve(model);
|
||||
|
||||
} else {
|
||||
|
||||
for(int m = 1; m <= 6; m++) {
|
||||
Solve(m);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
141
examples/dotnet/csharp/jobshop_ft06_sat.cs
Normal file
141
examples/dotnet/csharp/jobshop_ft06_sat.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.Sat;
|
||||
|
||||
public class JobshopFt06Sat
|
||||
{
|
||||
|
||||
public struct Task
|
||||
{
|
||||
public Task(IntVar s, IntVar e, IntervalVar i)
|
||||
{
|
||||
start = s;
|
||||
end = e;
|
||||
interval = i;
|
||||
}
|
||||
|
||||
public IntVar start;
|
||||
public IntVar end;
|
||||
public IntervalVar interval;
|
||||
}
|
||||
|
||||
static void Solve()
|
||||
{
|
||||
int[,] durations = new int[,] { {1, 3, 6, 7, 3, 6},
|
||||
{8, 5, 10, 10, 10, 4},
|
||||
{5, 4, 8, 9, 1, 7},
|
||||
{5, 5, 5, 3, 8, 9},
|
||||
{9, 3, 5, 4, 3, 1},
|
||||
{3, 3, 9, 10, 4, 1} };
|
||||
int[,] machines = new int[,] { {2, 0, 1, 3, 5, 4},
|
||||
{1, 2, 4, 5, 0, 3},
|
||||
{2, 3, 5, 0, 1, 4},
|
||||
{1, 0, 2, 3, 4, 5},
|
||||
{2, 1, 4, 5, 0, 3},
|
||||
{1, 3, 5, 0, 4, 2} };
|
||||
|
||||
int num_jobs = durations.GetLength(0);
|
||||
int num_machines = durations.GetLength(1);
|
||||
var all_jobs = Enumerable.Range(0, num_jobs);
|
||||
var all_machines = Enumerable.Range(0, num_machines);
|
||||
|
||||
int horizon = 0;
|
||||
foreach (int j in all_jobs)
|
||||
{
|
||||
foreach (int m in all_machines)
|
||||
{
|
||||
horizon += durations[j, m];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
|
||||
// Creates jobs.
|
||||
Task[,] all_tasks = new Task[num_jobs, num_machines];
|
||||
foreach (int j in all_jobs)
|
||||
{
|
||||
foreach (int m in all_machines)
|
||||
{
|
||||
IntVar start_var = model.NewIntVar(
|
||||
0, horizon, String.Format("start_{0}_{1}", j, m));
|
||||
int duration = durations[j, m];
|
||||
IntVar end_var = model.NewIntVar(
|
||||
0, horizon, String.Format("end_{0}_{1}", j, m));
|
||||
IntervalVar interval_var = model.NewIntervalVar(
|
||||
start_var, duration, end_var,
|
||||
String.Format("interval_{0}_{1}", j, m));
|
||||
all_tasks[j, m] = new Task(start_var, end_var, interval_var);
|
||||
}
|
||||
}
|
||||
|
||||
// Create disjuctive constraints.
|
||||
List<IntervalVar>[] machine_to_jobs = new List<IntervalVar>[num_machines];
|
||||
foreach (int m in all_machines)
|
||||
{
|
||||
machine_to_jobs[m] = new List<IntervalVar>();
|
||||
}
|
||||
foreach (int j in all_jobs)
|
||||
{
|
||||
foreach (int m in all_machines)
|
||||
{
|
||||
machine_to_jobs[machines[j, m]].Add(all_tasks[j, m].interval);
|
||||
}
|
||||
}
|
||||
foreach (int m in all_machines)
|
||||
{
|
||||
model.AddNoOverlap(machine_to_jobs[m]);
|
||||
}
|
||||
|
||||
// Precedences inside a job.
|
||||
foreach (int j in all_jobs)
|
||||
{
|
||||
for (int k = 0; k < num_machines - 1; ++k)
|
||||
{
|
||||
model.Add(all_tasks[j, k + 1].start >= all_tasks[j, k].end);
|
||||
}
|
||||
}
|
||||
|
||||
// Makespan objective.
|
||||
IntVar[] all_ends = new IntVar[num_jobs];
|
||||
foreach (int j in all_jobs)
|
||||
{
|
||||
all_ends[j] = all_tasks[j, num_machines - 1].end;
|
||||
}
|
||||
IntVar makespan = model.NewIntVar(0, horizon, "makespan");
|
||||
model.AddMaxEquality(makespan, all_ends);
|
||||
model.Minimize(makespan);
|
||||
|
||||
// Creates the solver and solve.
|
||||
CpSolver solver = new CpSolver();
|
||||
// Display a few solutions picked at random.
|
||||
CpSolverStatus status = solver.Solve(model);
|
||||
|
||||
// Statistics.
|
||||
Console.WriteLine("Statistics");
|
||||
Console.WriteLine(String.Format(" - solve status : {0}", status));
|
||||
Console.WriteLine(" - makespan : " + solver.ObjectiveValue);
|
||||
Console.WriteLine(" - conflicts : " + solver.NumConflicts());
|
||||
Console.WriteLine(" - branches : " + solver.NumBranches());
|
||||
Console.WriteLine(" - wall time : " + solver.WallTime() + " ms");
|
||||
}
|
||||
|
||||
static void Main() {
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
129
examples/dotnet/csharp/just_forgotten.cs
Normal file
129
examples/dotnet/csharp/just_forgotten.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// 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 JustForgotten
|
||||
{
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Just forgotten puzzle (Enigma 1517) in Google CP Solver.
|
||||
*
|
||||
* From http://www.f1compiler.com/samples/Enigma 201517.f1.html
|
||||
* """
|
||||
* Enigma 1517 Bob Walker, New Scientist magazine, October 25, 2008.
|
||||
*
|
||||
* Joe was furious when he forgot one of his bank account numbers.
|
||||
* He remembered that it had all the digits 0 to 9 in some order,
|
||||
* so he tried the following four sets without success:
|
||||
*
|
||||
* 9 4 6 2 1 5 7 8 3 0
|
||||
* 8 6 0 4 3 9 1 2 5 7
|
||||
* 1 6 4 0 2 9 7 8 5 3
|
||||
* 6 8 2 4 3 1 9 0 7 5
|
||||
*
|
||||
* When Joe finally remembered his account number, he realised that
|
||||
* in each set just four of the digits were in their correct position
|
||||
* and that, if one knew that, it was possible to work out his
|
||||
* account number. What was it?
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/google_or_tools/just_forgotten.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("JustForgotten");
|
||||
|
||||
|
||||
int rows = 4;
|
||||
int cols = 10;
|
||||
|
||||
// The four tries
|
||||
int[,] a = {{9,4,6,2,1,5,7,8,3,0},
|
||||
{8,6,0,4,3,9,1,2,5,7},
|
||||
{1,6,4,0,2,9,7,8,5,3},
|
||||
{6,8,2,4,3,1,9,0,7,5}};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(cols, 0, 9, "x");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
for(int r = 0; r < rows; r++) {
|
||||
solver.Add( (from c in Enumerable.Range(0, cols)
|
||||
select x[c] == a[r,c]).ToArray().Sum() == 4);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("Account number:");
|
||||
for(int j = 0; j < cols; j++) {
|
||||
Console.Write(x[j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
Console.WriteLine("The four tries, where '!' represents a correct digit:");
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
String c = " ";
|
||||
if (a[i,j] == x[j].Value()) {
|
||||
c = "!";
|
||||
}
|
||||
Console.Write("{0}{1} ", a[i,j], c);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
219
examples/dotnet/csharp/kakuro.cs
Normal file
219
examples/dotnet/csharp/kakuro.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class Kakuro
|
||||
{
|
||||
|
||||
/**
|
||||
* Ensure that the sum of the segments
|
||||
* in cc == res
|
||||
*
|
||||
*/
|
||||
public static void calc(Solver solver,
|
||||
int[] cc,
|
||||
IntVar[,] x,
|
||||
int res)
|
||||
{
|
||||
|
||||
// ensure that the values are positive
|
||||
int len = cc.Length / 2;
|
||||
for(int i = 0; i < len; i++) {
|
||||
solver.Add(x[cc[i*2]-1,cc[i*2+1]-1] >= 1);
|
||||
}
|
||||
|
||||
// sum the numbers
|
||||
solver.Add( (from i in Enumerable.Range(0, len)
|
||||
select x[cc[i*2]-1,cc[i*2+1]-1])
|
||||
.ToArray().Sum() == res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Kakuru puzzle.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Kakuro
|
||||
* """
|
||||
* The object of the puzzle is to insert a digit from 1 to 9 inclusive
|
||||
* into each white cell such that the sum of the numbers in each entry
|
||||
* matches the clue associated with it and that no digit is duplicated in
|
||||
* any entry. It is that lack of duplication that makes creating Kakuro
|
||||
* puzzles with unique solutions possible, and which means solving a Kakuro
|
||||
* puzzle involves investigating combinations more, compared to Sudoku in
|
||||
* which the focus is on permutations. There is an unwritten rule for
|
||||
* making Kakuro puzzles that each clue must have at least two numbers
|
||||
* that add up to it. This is because including one number is mathematically
|
||||
* trivial when solving Kakuro puzzles; one can simply disregard the
|
||||
* number entirely and subtract it from the clue it indicates.
|
||||
* """
|
||||
*
|
||||
* This model solves the problem at the Wikipedia page.
|
||||
* For a larger picture, see
|
||||
* http://en.wikipedia.org/wiki/File:Kakuro_black_box.svg
|
||||
*
|
||||
* The solution:
|
||||
* 9 7 0 0 8 7 9
|
||||
* 8 9 0 8 9 5 7
|
||||
* 6 8 5 9 7 0 0
|
||||
* 0 6 1 0 2 6 0
|
||||
* 0 0 4 6 1 3 2
|
||||
* 8 9 3 1 0 1 4
|
||||
* 3 1 2 0 0 2 1
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/kakuro.py
|
||||
* though this C# model has another representation of
|
||||
* the problem instance.
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Kakuro");
|
||||
|
||||
// size of matrix
|
||||
int n = 7;
|
||||
|
||||
// segments:
|
||||
// sum, the segments
|
||||
// Note: this is 1-based
|
||||
int[][] problem =
|
||||
{
|
||||
new int[] {16, 1,1, 1,2},
|
||||
new int[] {24, 1,5, 1,6, 1,7},
|
||||
new int[] {17, 2,1, 2,2},
|
||||
new int[] {29, 2,4, 2,5, 2,6, 2,7},
|
||||
new int[] {35, 3,1, 3,2, 3,3, 3,4, 3,5},
|
||||
new int[] { 7, 4,2, 4,3},
|
||||
new int[] { 8, 4,5, 4,6},
|
||||
new int[] {16, 5,3, 5,4, 5,5, 5,6, 5,7},
|
||||
new int[] {21, 6,1, 6,2, 6,3, 6,4},
|
||||
new int[] { 5, 6,6, 6,7},
|
||||
new int[] { 6, 7,1, 7,2, 7,3},
|
||||
new int[] { 3, 7,6, 7,7},
|
||||
|
||||
new int[] {23, 1,1, 2,1, 3,1},
|
||||
new int[] {30, 1,2, 2,2, 3,2, 4,2},
|
||||
new int[] {27, 1,5, 2,5, 3,5, 4,5, 5,5},
|
||||
new int[] {12, 1,6, 2,6},
|
||||
new int[] {16, 1,7, 2,7},
|
||||
new int[] {17, 2,4, 3,4},
|
||||
new int[] {15, 3,3, 4,3, 5,3, 6,3, 7,3},
|
||||
new int[] {12, 4,6, 5,6, 6,6, 7,6},
|
||||
new int[] { 7, 5,4, 6,4},
|
||||
new int[] { 7, 5,7, 6,7, 7,7},
|
||||
new int[] {11, 6,1, 7,1},
|
||||
new int[] {10, 6,2, 7,2}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int num_p = 24; // Number of segments
|
||||
|
||||
// The blanks
|
||||
// Note: 1-based
|
||||
int[,] blanks = {
|
||||
{1,3}, {1,4},
|
||||
{2,3},
|
||||
{3,6}, {3,7},
|
||||
{4,1}, {4,4}, {4,7},
|
||||
{5,1}, {5,2},
|
||||
{6,5},
|
||||
{7,4}, {7,5}
|
||||
};
|
||||
|
||||
int num_blanks = blanks.GetLength(0);
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 0, 9, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// fill the blanks with 0
|
||||
for(int i = 0; i < num_blanks; i++) {
|
||||
solver.Add(x[blanks[i,0]-1,blanks[i,1]-1]==0);
|
||||
}
|
||||
|
||||
for(int i = 0; i < num_p; i++) {
|
||||
int[] segment = problem[i];
|
||||
|
||||
// Remove the sum from the segment
|
||||
int[] s2 = new int[segment.Length-1];
|
||||
for(int j = 1; j < segment.Length; j++) {
|
||||
s2[j-1] = segment[j];
|
||||
}
|
||||
|
||||
// sum this segment
|
||||
calc(solver, s2, x, segment[0]);
|
||||
|
||||
// all numbers in this segment must be distinct
|
||||
int len = segment.Length / 2;
|
||||
solver.Add( (from j in Enumerable.Range(0, len)
|
||||
select x[s2[j * 2] - 1, s2[j * 2 + 1] - 1])
|
||||
.ToArray().AllDifferent());
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
int v = (int)x[i,j].Value();
|
||||
if (v > 0) {
|
||||
Console.Write(v + " ");
|
||||
} else {
|
||||
Console.Write(" ");
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
241
examples/dotnet/csharp/kenken2.cs
Normal file
241
examples/dotnet/csharp/kenken2.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class KenKen2
|
||||
{
|
||||
|
||||
/**
|
||||
* Ensure that the sum of the segments
|
||||
* in cc == res
|
||||
*
|
||||
*/
|
||||
public static void calc(Solver solver,
|
||||
int[] cc,
|
||||
IntVar[,] x,
|
||||
int res)
|
||||
{
|
||||
|
||||
int ccLen = cc.Length;
|
||||
if (ccLen == 4) {
|
||||
|
||||
// for two operands there's
|
||||
// a lot of possible variants
|
||||
IntVar a = x[cc[0]-1, cc[1]-1];
|
||||
IntVar b = x[cc[2]-1, cc[3]-1];
|
||||
|
||||
IntVar r1 = a + b == res;
|
||||
IntVar r2 = a * b == res;
|
||||
IntVar r3 = a * res == b;
|
||||
IntVar r4 = b * res == a;
|
||||
IntVar r5 = a - b == res;
|
||||
IntVar r6 = b - a == res;
|
||||
|
||||
solver.Add(r1+r2+r3+r4+r5+r6 >= 1);
|
||||
|
||||
} else {
|
||||
|
||||
// For length > 2 then res is either the sum
|
||||
// the the product of the segment
|
||||
|
||||
// sum the numbers
|
||||
int len = cc.Length / 2;
|
||||
IntVar[] xx = (from i in Enumerable.Range(0, len)
|
||||
select x[cc[i*2]-1,cc[i*2+1]-1]).ToArray();
|
||||
|
||||
// Sum
|
||||
IntVar this_sum = xx.Sum() == res;
|
||||
|
||||
// Product
|
||||
// IntVar this_prod = (xx.Prod() == res).Var(); // don't work
|
||||
IntVar this_prod;
|
||||
if (xx.Length == 3) {
|
||||
this_prod = (x[cc[0]-1,cc[1]-1] *
|
||||
x[cc[2]-1,cc[3]-1] *
|
||||
x[cc[4]-1,cc[5]-1]) == res;
|
||||
} else {
|
||||
this_prod = (x[cc[0]-1,cc[1]-1] *
|
||||
x[cc[2]-1,cc[3]-1] *
|
||||
x[cc[4]-1,cc[5]-1] *
|
||||
x[cc[6]-1,cc[7]-1]) == res;
|
||||
|
||||
}
|
||||
|
||||
solver.Add(this_sum + this_prod >= 1);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* KenKen puzzle.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/KenKen
|
||||
* """
|
||||
* KenKen or KEN-KEN is a style of arithmetic and logical puzzle sharing
|
||||
* several characteristics with sudoku. The name comes from Japanese and
|
||||
* is translated as 'square wisdom' or 'cleverness squared'.
|
||||
* ...
|
||||
* The objective is to fill the grid in with the digits 1 through 6 such that:
|
||||
*
|
||||
* * Each row contains exactly one of each digit
|
||||
* * Each column contains exactly one of each digit
|
||||
* * Each bold-outlined group of cells is a cage containing digits which
|
||||
* achieve the specified result using the specified mathematical operation:
|
||||
* addition (+),
|
||||
* subtraction (-),
|
||||
* multiplication (x),
|
||||
* and division (/).
|
||||
* (Unlike in Killer sudoku, digits may repeat within a group.)
|
||||
*
|
||||
* ...
|
||||
* More complex KenKen problems are formed using the principles described
|
||||
* above but omitting the symbols +, -, x and /, thus leaving them as
|
||||
* yet another unknown to be determined.
|
||||
* """
|
||||
*
|
||||
* The solution is:
|
||||
*
|
||||
* 5 6 3 4 1 2
|
||||
* 6 1 4 5 2 3
|
||||
* 4 5 2 3 6 1
|
||||
* 3 4 1 2 5 6
|
||||
* 2 3 6 1 4 5
|
||||
* 1 2 5 6 3 4
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/kenken2.py
|
||||
* though this C# model has another representation of
|
||||
* the problem instance.
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("KenKen2");
|
||||
|
||||
// size of matrix
|
||||
int n = 6;
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
// For a better view of the problem, see
|
||||
// http://en.wikipedia.org/wiki/File:KenKenProblem.svg
|
||||
|
||||
// hints
|
||||
// sum, the hints
|
||||
// Note: this is 1-based
|
||||
int[][] problem =
|
||||
{
|
||||
new int[] { 11, 1,1, 2,1},
|
||||
new int[] { 2, 1,2, 1,3},
|
||||
new int[] { 20, 1,4, 2,4},
|
||||
new int[] { 6, 1,5, 1,6, 2,6, 3,6},
|
||||
new int[] { 3, 2,2, 2,3},
|
||||
new int[] { 3, 2,5, 3,5},
|
||||
new int[] {240, 3,1, 3,2, 4,1, 4,2},
|
||||
new int[] { 6, 3,3, 3,4},
|
||||
new int[] { 6, 4,3, 5,3},
|
||||
new int[] { 7, 4,4, 5,4, 5,5},
|
||||
new int[] { 30, 4,5, 4,6},
|
||||
new int[] { 6, 5,1, 5,2},
|
||||
new int[] { 9, 5,6, 6,6},
|
||||
new int[] { 8, 6,1, 6,2, 6,3},
|
||||
new int[] { 2, 6,4, 6,5}
|
||||
};
|
||||
|
||||
|
||||
int num_p = problem.GetLength(0); // Number of segments
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
//
|
||||
// alldifferent rows and columns
|
||||
foreach(int i in RANGE) {
|
||||
// rows
|
||||
solver.Add( (from j in RANGE select x[i,j]).ToArray().AllDifferent());
|
||||
|
||||
// cols
|
||||
solver.Add( (from j in RANGE select x[j,i]).ToArray().AllDifferent());
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Calculate the segments
|
||||
for(int i = 0; i < num_p; i++) {
|
||||
|
||||
int[] segment = problem[i];
|
||||
|
||||
// Remove the sum from the segment
|
||||
int len = segment.Length-1;
|
||||
int[] s2 = new int[len];
|
||||
Array.Copy(segment, 1, s2, 0, len);
|
||||
|
||||
// sum this segment
|
||||
calc(solver, s2, x, segment[0]);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write(x[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
240
examples/dotnet/csharp/killer_sudoku.cs
Normal file
240
examples/dotnet/csharp/killer_sudoku.cs
Normal file
@@ -0,0 +1,240 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class KillerSudoku
|
||||
{
|
||||
|
||||
/**
|
||||
* Ensure that the sum of the segments
|
||||
* in cc == res
|
||||
*
|
||||
*/
|
||||
public static void calc(Solver solver,
|
||||
int[] cc,
|
||||
IntVar[,] x,
|
||||
int res)
|
||||
{
|
||||
|
||||
// sum the numbers
|
||||
int len = cc.Length / 2;
|
||||
solver.Add( (from i in Enumerable.Range(0, len)
|
||||
select x[cc[i*2]-1,cc[i*2+1]-1]).ToArray().Sum() == res);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Killer Sudoku.
|
||||
*
|
||||
* http://en.wikipedia.org/wiki/Killer_Sudoku
|
||||
* """
|
||||
* Killer sudoku (also killer su doku, sumdoku, sum doku, addoku, or
|
||||
* samunamupure) is a puzzle that combines elements of sudoku and kakuro.
|
||||
* Despite the name, the simpler killer sudokus can be easier to solve
|
||||
* than regular sudokus, depending on the solver's skill at mental arithmetic;
|
||||
* the hardest ones, however, can take hours to crack.
|
||||
*
|
||||
* ...
|
||||
*
|
||||
* The objective is to fill the grid with numbers from 1 to 9 in a way that
|
||||
* the following conditions are met:
|
||||
*
|
||||
* - Each row, column, and nonet contains each number exactly once.
|
||||
* - The sum of all numbers in a cage must match the small number printed
|
||||
* in its corner.
|
||||
* - No number appears more than once in a cage. (This is the standard rule
|
||||
* for killer sudokus, and implies that no cage can include more
|
||||
* than 9 cells.)
|
||||
*
|
||||
* In 'Killer X', an additional rule is that each of the long diagonals
|
||||
* contains each number once.
|
||||
* """
|
||||
*
|
||||
* Here we solve the problem from the Wikipedia page, also shown here
|
||||
* http://en.wikipedia.org/wiki/File:Killersudoku_color.svg
|
||||
*
|
||||
* The output is:
|
||||
* 2 1 5 6 4 7 3 9 8
|
||||
* 3 6 8 9 5 2 1 7 4
|
||||
* 7 9 4 3 8 1 6 5 2
|
||||
* 5 8 6 2 7 4 9 3 1
|
||||
* 1 4 2 5 9 3 8 6 7
|
||||
* 9 7 3 8 1 6 4 2 5
|
||||
* 8 2 1 7 3 9 5 4 6
|
||||
* 6 5 9 4 2 8 7 1 3
|
||||
* 4 3 7 1 6 5 2 8 9
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/killer_sudoku.py
|
||||
* though this C# model has another representation of
|
||||
* the problem instance.
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("KillerSudoku");
|
||||
|
||||
// size of matrix
|
||||
int cell_size = 3;
|
||||
IEnumerable<int> CELL = Enumerable.Range(0, cell_size);
|
||||
int n = cell_size*cell_size;
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
// For a better view of the problem, see
|
||||
// http://en.wikipedia.org/wiki/File:Killersudoku_color.svg
|
||||
|
||||
// hints
|
||||
// sum, the hints
|
||||
// Note: this is 1-based
|
||||
int[][] problem =
|
||||
{
|
||||
new int[] { 3, 1,1, 1,2},
|
||||
new int[] {15, 1,3, 1,4, 1,5},
|
||||
new int[] {22, 1,6, 2,5, 2,6, 3,5},
|
||||
new int[] {4, 1,7, 2,7},
|
||||
new int[] {16, 1,8, 2,8},
|
||||
new int[] {15, 1,9, 2,9, 3,9, 4,9},
|
||||
new int[] {25, 2,1, 2,2, 3,1, 3,2},
|
||||
new int[] {17, 2,3, 2,4},
|
||||
new int[] { 9, 3,3, 3,4, 4,4},
|
||||
new int[] { 8, 3,6, 4,6, 5,6},
|
||||
new int[] {20, 3,7, 3,8, 4,7},
|
||||
new int[] { 6, 4,1, 5,1},
|
||||
new int[] {14, 4,2, 4,3},
|
||||
new int[] {17, 4,5, 5,5, 6,5},
|
||||
new int[] {17, 4,8, 5,7, 5,8},
|
||||
new int[] {13, 5,2, 5,3, 6,2},
|
||||
new int[] {20, 5,4, 6,4, 7,4},
|
||||
new int[] {12, 5,9, 6,9},
|
||||
new int[] {27, 6,1, 7,1, 8,1, 9,1},
|
||||
new int[] { 6, 6,3, 7,2, 7,3},
|
||||
new int[] {20, 6,6, 7,6, 7,7},
|
||||
new int[] { 6, 6,7, 6,8},
|
||||
new int[] {10, 7,5, 8,4, 8,5, 9,4},
|
||||
new int[] {14, 7,8, 7,9, 8,8, 8,9},
|
||||
new int[] { 8, 8,2, 9,2},
|
||||
new int[] {16, 8,3, 9,3},
|
||||
new int[] {15, 8,6, 8,7},
|
||||
new int[] {13, 9,5, 9,6, 9,7},
|
||||
new int[] {17, 9,8, 9,9}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int num_p = 29; // Number of segments
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 0, 9, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
//
|
||||
// The first three constraints is the same as for sudokus.cs
|
||||
//
|
||||
// alldifferent rows and columns
|
||||
foreach(int i in RANGE) {
|
||||
// rows
|
||||
solver.Add( (from j in RANGE
|
||||
select x[i,j]).ToArray().AllDifferent());
|
||||
|
||||
// cols
|
||||
solver.Add( (from j in RANGE
|
||||
select x[j,i]).ToArray().AllDifferent());
|
||||
|
||||
}
|
||||
|
||||
// cells
|
||||
foreach(int i in CELL) {
|
||||
foreach(int j in CELL) {
|
||||
solver.Add( (from di in CELL
|
||||
from dj in CELL
|
||||
select x[i*cell_size+di, j*cell_size+dj]
|
||||
).ToArray().AllDifferent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sum the segments and ensure alldifferent
|
||||
for(int i = 0; i < num_p; i++) {
|
||||
int[] segment = problem[i];
|
||||
|
||||
// Remove the sum from the segment
|
||||
int[] s2 = new int[segment.Length-1];
|
||||
for(int j = 1; j < segment.Length; j++) {
|
||||
s2[j-1] = segment[j];
|
||||
}
|
||||
|
||||
// sum this segment
|
||||
calc(solver, s2, x, segment[0]);
|
||||
|
||||
// all numbers in this segment must be distinct
|
||||
int len = segment.Length / 2;
|
||||
solver.Add( (from j in Enumerable.Range(0, len)
|
||||
select x[s2[j*2]-1, s2[j*2+1]-1])
|
||||
.ToArray().AllDifferent());
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
int v = (int)x[i,j].Value();
|
||||
if (v > 0) {
|
||||
Console.Write(v + " ");
|
||||
} else {
|
||||
Console.Write(" ");
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
184
examples/dotnet/csharp/labeled_dice.cs
Normal file
184
examples/dotnet/csharp/labeled_dice.cs
Normal file
@@ -0,0 +1,184 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class LabeledDice
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Labeled dice problem.
|
||||
*
|
||||
* From Jim Orlin 'Colored letters, labeled dice: a logic puzzle'
|
||||
* http://jimorlin.wordpress.com/2009/02/17/colored-letters-labeled-dice-a-logic-puzzle/
|
||||
* """
|
||||
* My daughter Jenn bough a puzzle book, and showed me a cute puzzle. There
|
||||
* are 13 words as follows: BUOY, CAVE, CELT, FLUB, FORK, HEMP, JUDY,
|
||||
* JUNK, LIMN, QUIP, SWAG, VISA, WISH.
|
||||
*
|
||||
* There are 24 different letters that appear in the 13 words. The question
|
||||
* is: can one assign the 24 letters to 4 different cubes so that the
|
||||
* four letters of each word appears on different cubes. (There is one
|
||||
* letter from each word on each cube.) It might be fun for you to try
|
||||
* it. I'll give a small hint at the end of this post. The puzzle was
|
||||
* created by Humphrey Dudley.
|
||||
* """
|
||||
*
|
||||
* Jim Orlin's followup 'Update on Logic Puzzle':
|
||||
* http://jimorlin.wordpress.com/2009/02/21/update-on-logic-puzzle/
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/labeled_dice.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("LabeledDice");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 4;
|
||||
int m = 24;
|
||||
|
||||
int A = 0;
|
||||
int B = 1;
|
||||
int C = 2;
|
||||
int D = 3;
|
||||
int E = 4;
|
||||
int F = 5;
|
||||
int G = 6;
|
||||
int H = 7;
|
||||
int I = 8;
|
||||
int J = 9;
|
||||
int K = 10;
|
||||
int L = 11;
|
||||
int M = 12;
|
||||
int N = 13;
|
||||
int O = 14;
|
||||
int P = 15;
|
||||
int Q = 16;
|
||||
int R = 17;
|
||||
int S = 18;
|
||||
int T = 19;
|
||||
int U = 20;
|
||||
int V = 21;
|
||||
int W = 22;
|
||||
int Y = 23;
|
||||
|
||||
|
||||
String[] letters_str = {"A","B","C","D","E","F","G","H","I","J","K","L","M",
|
||||
"N","O","P","Q","R","S","T","U","V","W","Y"};
|
||||
|
||||
int num_words = 13;
|
||||
int[,] words =
|
||||
{
|
||||
{B,U,O,Y},
|
||||
{C,A,V,E},
|
||||
{C,E,L,T},
|
||||
{F,L,U,B},
|
||||
{F,O,R,K},
|
||||
{H,E,M,P},
|
||||
{J,U,D,Y},
|
||||
{J,U,N,K},
|
||||
{L,I,M,N},
|
||||
{Q,U,I,P},
|
||||
{S,W,A,G},
|
||||
{V,I,S,A},
|
||||
{W,I,S,H}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] dice = solver.MakeIntVarArray(m, 0, n-1, "dice");
|
||||
IntVar[] gcc = solver.MakeIntVarArray(n, 6, 6, "gcc");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
|
||||
// the letters in a word must be on a different die
|
||||
for(int i = 0; i < num_words; i++) {
|
||||
solver.Add( (from j in Enumerable.Range(0, n)
|
||||
select dice[words[i,j]]
|
||||
).ToArray().AllDifferent());
|
||||
}
|
||||
|
||||
// there must be exactly 6 letters of each die
|
||||
/*
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add( ( from j in Enumerable.Range(0, m)
|
||||
select (dice[j] == i)
|
||||
).ToArray().Sum() == 6 );
|
||||
}
|
||||
*/
|
||||
// Use Distribute (Global Cardinality Count) instead.
|
||||
solver.Add(dice.Distribute(gcc));
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(dice,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int d = 0; d < n; d++) {
|
||||
Console.Write("die {0}: ", d);
|
||||
for(int i = 0; i < m; i++) {
|
||||
if (dice[i].Value() == d) {
|
||||
Console.Write(letters_str[i]);
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("The words with the cube label:");
|
||||
for(int i = 0; i < num_words; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write("{0} ({1})", letters_str[words[i,j]], dice[words[i,j]].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
113
examples/dotnet/csharp/langford.cs
Normal file
113
examples/dotnet/csharp/langford.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Langford
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Langford number problem.
|
||||
* See http://www.hakank.org/or-tools/langford.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int k = 8, int num_sol = 0)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Langford");
|
||||
|
||||
Console.WriteLine("k: {0}", k);
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int p = 2*k;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] position = solver.MakeIntVarArray(p, 0, p-1, "position");
|
||||
IntVar[] solution = solver.MakeIntVarArray(p, 1, k, "solution");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(position.AllDifferent());
|
||||
|
||||
for(int i = 1; i <= k; i++) {
|
||||
solver.Add(position[i+k-1] - (position[i-1] + solver.MakeIntVar(i+1,i+1)) == 0);
|
||||
solver.Add(solution.Element(position[i-1]) == i);
|
||||
solver.Add(solution.Element(position[k+i-1]) == i);
|
||||
}
|
||||
|
||||
// Symmetry breaking
|
||||
solver.Add(solution[0] < solution[2*k-1]);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(position,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int num_solutions = 0;
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("solution : ");
|
||||
for(int i = 0; i < p; i++) {
|
||||
Console.Write(solution[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
num_solutions++;
|
||||
if (num_sol > 0 && num_solutions >= num_sol) {
|
||||
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 k = 8;
|
||||
int num_sol = 0; // 0: print all solutions
|
||||
|
||||
if (args.Length > 0) {
|
||||
k = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (args.Length > 1) {
|
||||
num_sol = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
Solve(k, num_sol);
|
||||
|
||||
}
|
||||
}
|
||||
91
examples/dotnet/csharp/least_diff.cs
Normal file
91
examples/dotnet/csharp/least_diff.cs
Normal file
@@ -0,0 +1,91 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class LeastDiff
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solve the Least diff problem
|
||||
* For more info, see http://www.hakank.org/google_or_tools/least_diff.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("LeastDiff");
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar A = solver.MakeIntVar(0, 9, "A");
|
||||
IntVar B = solver.MakeIntVar(0, 9, "B");
|
||||
IntVar C = solver.MakeIntVar(0, 9, "C");
|
||||
IntVar D = solver.MakeIntVar(0, 9, "D");
|
||||
IntVar E = solver.MakeIntVar(0, 9, "E");
|
||||
IntVar F = solver.MakeIntVar(0, 9, "F");
|
||||
IntVar G = solver.MakeIntVar(0, 9, "G");
|
||||
IntVar H = solver.MakeIntVar(0, 9, "H");
|
||||
IntVar I = solver.MakeIntVar(0, 9, "I");
|
||||
IntVar J = solver.MakeIntVar(0, 9, "J");
|
||||
|
||||
IntVar[] all = new IntVar[] {A,B,C,D,E,F,G,H,I,J};
|
||||
int[] coeffs = {10000,1000,100,10,1};
|
||||
IntVar x = new IntVar[]{A,B,C,D,E}.ScalProd(coeffs).Var();
|
||||
IntVar y = new IntVar[]{F,G,H,I,J}.ScalProd(coeffs).Var();
|
||||
IntVar diff = (x - y).VarWithName("diff");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(all.AllDifferent());
|
||||
solver.Add(A > 0);
|
||||
solver.Add(F > 0);
|
||||
solver.Add(diff > 0);
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = diff.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all,
|
||||
Solver.CHOOSE_PATH,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("{0} - {1} = {2} ({3}",x.Value(), y.Value(), diff.Value(), diff.ToString());
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
193
examples/dotnet/csharp/lectures.cs
Normal file
193
examples/dotnet/csharp/lectures.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Lectures
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Lectures problem in Google CP Solver.
|
||||
*
|
||||
* Biggs: Discrete Mathematics (2nd ed), page 187.
|
||||
* """
|
||||
* Suppose we wish to schedule six one-hour lectures, v1, v2, v3, v4, v5, v6.
|
||||
* Among the the potential audience there are people who wish to hear both
|
||||
*
|
||||
* - v1 and v2
|
||||
* - v1 and v4
|
||||
* - v3 and v5
|
||||
* - v2 and v6
|
||||
* - v4 and v5
|
||||
* - v5 and v6
|
||||
* - v1 and v6
|
||||
*
|
||||
* How many hours are necessary in order that the lectures can be given
|
||||
* without clashes?
|
||||
* """
|
||||
*
|
||||
* Note: This can be seen as a coloring problem.
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/lectures.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Lectures");
|
||||
|
||||
//
|
||||
// The schedule requirements:
|
||||
// lecture a cannot be held at the same time as b
|
||||
// Note: 1-based (compensated in the constraints).
|
||||
int[,] g =
|
||||
{
|
||||
{1, 2},
|
||||
{1, 4},
|
||||
{3, 5},
|
||||
{2, 6},
|
||||
{4, 5},
|
||||
{5, 6},
|
||||
{1, 6}
|
||||
};
|
||||
|
||||
// number of nodes
|
||||
int n = 6;
|
||||
|
||||
// number of edges
|
||||
int edges = g.GetLength(0);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
//
|
||||
// declare variables
|
||||
//
|
||||
IntVar[] v = solver.MakeIntVarArray(n, 0, n-1,"v");
|
||||
|
||||
// Maximum color (hour) to minimize.
|
||||
// Note: since C# is 0-based, the
|
||||
// number of colors is max_c+1.
|
||||
IntVar max_c = v.Max().VarWithName("max_c");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// Ensure that there are no clashes
|
||||
// also, adjust to 0-base.
|
||||
for(int i = 0; i < edges; i++) {
|
||||
solver.Add(v[g[i,0]-1] != v[g[i,1]-1]);
|
||||
}
|
||||
|
||||
// Symmetry breaking:
|
||||
// - v0 has the color 0,
|
||||
// - v1 has either color 0 or 1
|
||||
solver.Add(v[0] == 0);
|
||||
solver.Add(v[1] <= 1);
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = max_c.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(v,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("\nmax hours: {0}", max_c.Value()+1);
|
||||
Console.WriteLine("v: " +
|
||||
String.Join(" ", (from i in Enumerable.Range(0, n)
|
||||
select v[i].Value()).ToArray()));
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.WriteLine("Lecture {0} at {1}h", i, v[i].Value());
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
// Print the current solution
|
||||
public static void PrintOneSolution(IntVar[] positions,
|
||||
int rows,
|
||||
int cols,
|
||||
int num_solution)
|
||||
{
|
||||
|
||||
Console.WriteLine("Solution {0}", num_solution);
|
||||
|
||||
// Create empty board
|
||||
int[,] board = new int[rows, cols];
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
board[i,j] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill board with solution value
|
||||
for(int k = 0; k < rows*cols; k++) {
|
||||
int position = (int)positions[k].Value();
|
||||
board[position / cols, position % cols] = k + 1;
|
||||
}
|
||||
|
||||
PrintMatrix(board);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Pretty print of the matrix
|
||||
public static void PrintMatrix(int[,] game)
|
||||
{
|
||||
int rows = game.GetLength(0);
|
||||
int cols = game.GetLength(1);
|
||||
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
if (game[i,j] == 0) {
|
||||
Console.Write(" .");
|
||||
} else {
|
||||
Console.Write(" {0,2}", game[i,j] );
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
112
examples/dotnet/csharp/magic_sequence.cs
Normal file
112
examples/dotnet/csharp/magic_sequence.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class MagicSequence
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Magic sequence problem.
|
||||
*
|
||||
* This is a port of the Python model
|
||||
* https://code.google.com/p/or-tools/source/browse/trunk/python/magic_sequence_distribute.py
|
||||
* """
|
||||
* This models aims at building a sequence of numbers such that the number of
|
||||
* occurrences of i in this sequence is equal to the value of the ith number.
|
||||
* It uses an aggregated formulation of the count expression called
|
||||
* distribute().
|
||||
* """
|
||||
*
|
||||
*/
|
||||
private static void Solve(int size)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("MagicSequence");
|
||||
|
||||
Console.WriteLine("\nSize: {0}", size);
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int[] all_values = new int[size];
|
||||
for (int i = 0; i < size; i++) {
|
||||
all_values[i] = i;
|
||||
}
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] all_vars = solver.MakeIntVarArray(size, 0, size - 1, "vars");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(all_vars.Distribute(all_values, all_vars));
|
||||
solver.Add(all_vars.Sum() == size);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all_vars,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < size; i++) {
|
||||
Console.Write(all_vars[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
if (args.Length > 0) {
|
||||
|
||||
int size = Convert.ToInt32(args[0]);
|
||||
Solve(size);
|
||||
|
||||
} else {
|
||||
// Let's test some diferent sizes
|
||||
foreach(int i in new int[] {2, 10, 100, 200, 500}) {
|
||||
Solve(i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
140
examples/dotnet/csharp/magic_square.cs
Normal file
140
examples/dotnet/csharp/magic_square.cs
Normal file
@@ -0,0 +1,140 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class MagicSquare
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves the Magic Square problem.
|
||||
* See http://www.hakank.org/or-tools/magic_square.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n = 4, int num = 0, int print = 1)
|
||||
{
|
||||
Solver solver = new Solver("MagicSquare");
|
||||
|
||||
Console.WriteLine("n: {0}", n);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n*n, "x");
|
||||
// for the branching
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
long s = (n * (n * n + 1)) / 2;
|
||||
Console.WriteLine("s: " + s);
|
||||
|
||||
IntVar[] diag1 = new IntVar[n];
|
||||
IntVar[] diag2 = new IntVar[n];
|
||||
for(int i = 0; i < n; i++) {
|
||||
IntVar[] row = new IntVar[n];
|
||||
for(int j = 0; j < n; j++) {
|
||||
row[j] = x[i,j];
|
||||
}
|
||||
// sum row to s
|
||||
solver.Add(row.Sum() == s);
|
||||
|
||||
diag1[i] = x[i,i];
|
||||
diag2[i] = x[i,n - i - 1];
|
||||
}
|
||||
|
||||
// sum diagonals to s
|
||||
solver.Add(diag1.Sum() == s);
|
||||
solver.Add(diag2.Sum() == s);
|
||||
|
||||
// sum columns to s
|
||||
for(int j = 0; j < n; j++) {
|
||||
IntVar[] col = new IntVar[n];
|
||||
for(int i = 0; i < n; i++) {
|
||||
col[i] = x[i,j];
|
||||
}
|
||||
solver.Add(col.Sum() == s);
|
||||
}
|
||||
|
||||
// all are different
|
||||
solver.Add(x_flat.AllDifferent());
|
||||
|
||||
// symmetry breaking: upper left is 1
|
||||
// solver.Add(x[0,0] == 1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int c = 0;
|
||||
while (solver.NextSolution()) {
|
||||
if (print != 0) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write(x[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
c++;
|
||||
if (num > 0 && c >= num) {
|
||||
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 = 4;
|
||||
int num = 0;
|
||||
int print = 1;
|
||||
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (args.Length > 1) {
|
||||
num = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
if (args.Length > 2) {
|
||||
print = Convert.ToInt32(args[2]);
|
||||
}
|
||||
|
||||
Solve(n, num, print);
|
||||
}
|
||||
}
|
||||
131
examples/dotnet/csharp/magic_square_and_cards.cs
Normal file
131
examples/dotnet/csharp/magic_square_and_cards.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class MagicSquareAndCards
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Magic squares and cards problem.
|
||||
*
|
||||
* Martin Gardner (July 1971)
|
||||
* """
|
||||
* Allowing duplicates values, what is the largest constant sum for an order-3
|
||||
* magic square that can be formed with nine cards from the deck.
|
||||
* """
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/magic_square_and_cards.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n=3)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("MagicSquareAndCards");
|
||||
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, 13, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
IntVar s = solver.MakeIntVar(1, 13*4, "s");
|
||||
IntVar[] counts = solver.MakeIntVarArray(14, 0, 4, "counts");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
solver.Add(x_flat.Distribute(counts));
|
||||
|
||||
// the standard magic square constraints (sans all_different)
|
||||
foreach(int i in RANGE) {
|
||||
// rows
|
||||
solver.Add( (from j in RANGE select x[i,j]).ToArray().Sum() == s);
|
||||
|
||||
// columns
|
||||
solver.Add( (from j in RANGE select x[j,i]).ToArray().Sum() == s);
|
||||
}
|
||||
|
||||
// diagonals
|
||||
solver.Add( (from i in RANGE select x[i,i]).ToArray().Sum() == s);
|
||||
solver.Add( (from i in RANGE select x[i,n-i-1]).ToArray().Sum() == s);
|
||||
|
||||
|
||||
// redundant constraint
|
||||
solver.Add(counts.Sum() == n*n);
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = s.Maximize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("s: {0}", s.Value());
|
||||
Console.Write("counts:");
|
||||
for(int i = 0; i < 14; i++) {
|
||||
Console.Write(counts[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write(x[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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 = 3;
|
||||
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(n);
|
||||
}
|
||||
}
|
||||
96
examples/dotnet/csharp/map.cs
Normal file
96
examples/dotnet/csharp/map.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Map
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solves a simple map coloring problem.
|
||||
*
|
||||
* See http://www.hakank.org/google_or_tools/map.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Map");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int Belgium = 0;
|
||||
int Denmark = 1;
|
||||
int France = 2;
|
||||
int Germany = 3;
|
||||
int Netherlands = 4;
|
||||
int Luxembourg = 5;
|
||||
|
||||
int n = 6;
|
||||
int max_num_colors = 4;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] color = solver.MakeIntVarArray(n, 1, max_num_colors, "color");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(color[France] != color[Belgium]);
|
||||
solver.Add(color[France] != color[Luxembourg]);
|
||||
solver.Add(color[France] != color[Germany]);
|
||||
solver.Add(color[Luxembourg] != color[Germany]);
|
||||
solver.Add(color[Luxembourg] != color[Belgium]);
|
||||
solver.Add(color[Belgium] != color[Netherlands]);
|
||||
solver.Add(color[Belgium] != color[Germany]);
|
||||
solver.Add(color[Germany] != color[Netherlands]);
|
||||
solver.Add(color[Germany] != color[Denmark]);
|
||||
|
||||
// Symmetry breaking
|
||||
solver.Add(color[Belgium] == 1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(color,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("colors: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", color[i].Value());
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
107
examples/dotnet/csharp/map2.cs
Normal file
107
examples/dotnet/csharp/map2.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Map2
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solves a simple map coloring problem.
|
||||
*
|
||||
* Alternative version, using a matrix to represent
|
||||
* the neighbours.
|
||||
*
|
||||
* See http://www.hakank.org/google_or_tools/map.py
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Map2");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int Belgium = 0;
|
||||
int Denmark = 1;
|
||||
int France = 2;
|
||||
int Germany = 3;
|
||||
int Netherlands = 4;
|
||||
int Luxembourg = 5;
|
||||
|
||||
int n = 6;
|
||||
int max_num_colors = 4;
|
||||
|
||||
int[,] neighbours = {{France, Belgium},
|
||||
{France, Luxembourg},
|
||||
{France, Germany},
|
||||
{Luxembourg, Germany},
|
||||
{Luxembourg, Belgium},
|
||||
{Belgium, Netherlands},
|
||||
{Belgium, Germany},
|
||||
{Germany, Netherlands},
|
||||
{Germany, Denmark}};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] color = solver.MakeIntVarArray(n, 1, max_num_colors, "color");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < neighbours.GetLength(0); i++) {
|
||||
solver.Add(color[neighbours[i,0]] != color[neighbours[i,1]]);
|
||||
}
|
||||
|
||||
// Symmetry breaking
|
||||
solver.Add(color[Belgium] == 1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(color,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("colors: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", color[i].Value());
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
144
examples/dotnet/csharp/marathon2.cs
Normal file
144
examples/dotnet/csharp/marathon2.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Marathon2
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Marathon puzzle.
|
||||
*
|
||||
* From Xpress example
|
||||
* http://www.dashoptimization.com/home/cgi-bin/example.pl?id=mosel_puzzle_5_3
|
||||
* """
|
||||
* Dominique, Ignace, Naren, Olivier, Philippe, and Pascal
|
||||
* have arrived as the first six at the Paris marathon.
|
||||
* Reconstruct their arrival order from the following
|
||||
* information:
|
||||
* a) Olivier has not arrived last
|
||||
* b) Dominique, Pascal and Ignace have arrived before Naren
|
||||
* and Olivier
|
||||
* c) Dominique who was third last year has improved this year.
|
||||
* d) Philippe is among the first four.
|
||||
* e) Ignace has arrived neither in second nor third position.
|
||||
* f) Pascal has beaten Naren by three positions.
|
||||
* g) Neither Ignace nor Dominique are on the fourth position.
|
||||
*
|
||||
* (c) 2002 Dash Associates
|
||||
* author: S. Heipcke, Mar. 2002
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/marathon2.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Marathon2");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 6;
|
||||
String[] runners_str = {"Dominique", "Ignace", "Naren",
|
||||
"Olivier", "Philippe", "Pascal"};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] runners = solver.MakeIntVarArray(n, 1, n, "runners");
|
||||
IntVar Dominique = runners[0];
|
||||
IntVar Ignace = runners[1];
|
||||
IntVar Naren = runners[2];
|
||||
IntVar Olivier = runners[3];
|
||||
IntVar Philippe = runners[4];
|
||||
IntVar Pascal = runners[5];
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(runners.AllDifferent());
|
||||
|
||||
// a: Olivier not last
|
||||
solver.Add(Olivier != n);
|
||||
|
||||
// b: Dominique, Pascal and Ignace before Naren and Olivier
|
||||
solver.Add(Dominique < Naren);
|
||||
solver.Add(Dominique < Olivier);
|
||||
solver.Add(Pascal < Naren);
|
||||
solver.Add(Pascal < Olivier);
|
||||
solver.Add(Ignace < Naren);
|
||||
solver.Add(Ignace < Olivier);
|
||||
|
||||
// c: Dominique better than third
|
||||
solver.Add(Dominique < 3);
|
||||
|
||||
// d: Philippe is among the first four
|
||||
solver.Add(Philippe <= 4);
|
||||
|
||||
// e: Ignace neither second nor third
|
||||
solver.Add(Ignace != 2);
|
||||
solver.Add(Ignace != 3);
|
||||
|
||||
// f: Pascal three places earlier than Naren
|
||||
solver.Add(Pascal + 3 == Naren);
|
||||
|
||||
// g: Neither Ignace nor Dominique on fourth position
|
||||
solver.Add(Ignace != 4);
|
||||
solver.Add(Dominique != 4);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(runners,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
int[] runners_val = new int[n];
|
||||
Console.Write("runners: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
runners_val[i] = (int)runners[i].Value();
|
||||
Console.Write(runners_val[i] + " ");
|
||||
}
|
||||
Console.WriteLine("\nPlaces:");
|
||||
for(int i = 1; i < n+1; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (runners_val[j] == i) {
|
||||
Console.WriteLine("{0}: {1}", i, runners_str[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
170
examples/dotnet/csharp/max_flow_taha.cs
Normal file
170
examples/dotnet/csharp/max_flow_taha.cs
Normal file
@@ -0,0 +1,170 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class MaxFlowTaha
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Max flow problem.
|
||||
*
|
||||
* From Taha "Introduction to Operations Research", Example 6.4-2
|
||||
*
|
||||
* Translated from the AMPL code at
|
||||
* http://taha.ineg.uark.edu/maxflo.txt
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/max_flow_taha.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("MaxFlowTaha");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 5;
|
||||
int start = 0;
|
||||
int end = n-1;
|
||||
|
||||
IEnumerable<int> NODES = Enumerable.Range(0, n);
|
||||
|
||||
// cost matrix
|
||||
int[,] c = {
|
||||
{0, 20, 30, 10, 0},
|
||||
{0, 0, 40, 0, 30},
|
||||
{0, 0, 0, 10, 20},
|
||||
{0, 0, 5, 0, 20},
|
||||
{0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = new IntVar[n,n];
|
||||
foreach(int i in NODES) {
|
||||
foreach(int j in NODES) {
|
||||
x[i,j] = solver.MakeIntVar(0, c[i,j], "x");
|
||||
}
|
||||
}
|
||||
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
IntVar[] out_flow = solver.MakeIntVarArray(n, 0, 1000, "out_flow");
|
||||
IntVar[] in_flow = solver.MakeIntVarArray(n, 0, 1000, "in_flow");
|
||||
IntVar total = solver.MakeIntVar(0, 10000, "total");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add( (from j in NODES
|
||||
where c[start,j] > 0
|
||||
select x[start,j]
|
||||
).ToArray().Sum() == total);
|
||||
|
||||
foreach(int i in NODES) {
|
||||
|
||||
var in_flow_sum = (from j in NODES
|
||||
where c[j,i] > 0
|
||||
select x[j,i]
|
||||
);
|
||||
if (in_flow_sum.Count() > 0) {
|
||||
solver.Add(in_flow_sum.ToArray().Sum() == in_flow[i]);
|
||||
}
|
||||
|
||||
var out_flow_sum = (from j in NODES
|
||||
where c[i,j] > 0
|
||||
select x[i,j]
|
||||
);
|
||||
if (out_flow_sum.Count() > 0) {
|
||||
solver.Add(out_flow_sum.ToArray().Sum() == out_flow[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// in_flow == out_flow
|
||||
foreach(int i in NODES) {
|
||||
if (i != start && i != end) {
|
||||
solver.Add(out_flow[i] == in_flow[i]);
|
||||
}
|
||||
}
|
||||
|
||||
var s1 = (from i in NODES where c[i,start] > 0 select x[i,start]);
|
||||
if (s1.Count() > 0) {
|
||||
solver.Add(s1.ToArray().Sum() == 0);
|
||||
}
|
||||
|
||||
var s2 = (from j in NODES where c[end, j] > 0 select x[end,j]);
|
||||
if (s2.Count() > 0) {
|
||||
solver.Add(s2.ToArray().Sum() == 0);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = total.Maximize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat.Concat(in_flow).Concat(out_flow).ToArray(),
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("total: {0}",total.Value());
|
||||
Console.Write("in_flow : ");
|
||||
foreach(int i in NODES) {
|
||||
Console.Write(in_flow[i].Value() + " ");
|
||||
}
|
||||
Console.Write("\nout_flow: ");
|
||||
foreach(int i in NODES) {
|
||||
Console.Write(out_flow[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
foreach(int i in NODES) {
|
||||
foreach(int j in NODES) {
|
||||
Console.Write("{0,2} ", x[i,j].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
165
examples/dotnet/csharp/max_flow_winston1.cs
Normal file
165
examples/dotnet/csharp/max_flow_winston1.cs
Normal file
@@ -0,0 +1,165 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class MaxFlowWinston1
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Max flow problem.
|
||||
*
|
||||
* From Winston 'Operations Research', page 420f, 423f
|
||||
* Sunco Oil example.
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/max_flow_winston1.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("MaxFlowWinston1");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 5;
|
||||
IEnumerable<int> NODES = Enumerable.Range(0, n);
|
||||
|
||||
// The arcs
|
||||
// Note:
|
||||
// This is 1-based to be compatible with other implementations.
|
||||
//
|
||||
int[,] arcs1 = {
|
||||
{1, 2},
|
||||
{1, 3},
|
||||
{2, 3},
|
||||
{2, 4},
|
||||
{3, 5},
|
||||
{4, 5},
|
||||
{5, 1}
|
||||
};
|
||||
|
||||
// Capacities
|
||||
int [] cap = {2,3,3,4,2,1,100};
|
||||
|
||||
// Convert arcs to 0-based
|
||||
int num_arcs = arcs1.GetLength(0);
|
||||
IEnumerable<int> ARCS = Enumerable.Range(0, num_arcs);
|
||||
int[,] arcs = new int[num_arcs, 2];
|
||||
foreach(int i in ARCS) {
|
||||
for(int j = 0; j < 2; j++) {
|
||||
arcs[i,j] = arcs1[i,j] - 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert arcs to matrix (for sanity checking below)
|
||||
int[,] mat = new int[num_arcs, num_arcs];
|
||||
foreach(int i in NODES) {
|
||||
foreach(int j in NODES) {
|
||||
int c = 0;
|
||||
foreach(int k in ARCS) {
|
||||
if (arcs[k,0] == i && arcs[k,1] == j) {
|
||||
c = 1;
|
||||
}
|
||||
}
|
||||
mat[i,j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] flow = solver.MakeIntVarMatrix(n, n, 0, 200, "flow");
|
||||
IntVar z = flow[n-1, 0].VarWithName("z");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// capacity of arcs
|
||||
foreach(int i in ARCS) {
|
||||
solver.Add(flow[arcs[i,0], arcs[i,1]] <= cap[i]);
|
||||
}
|
||||
|
||||
// inflows == outflows
|
||||
foreach(int i in NODES) {
|
||||
var s1 = (from k in ARCS
|
||||
where arcs[k,1] == i
|
||||
select flow[arcs[k,0], arcs[k,1]]
|
||||
).ToArray().Sum();
|
||||
|
||||
var s2 = (from k in ARCS
|
||||
where arcs[k,0] == i
|
||||
select flow[arcs[k,0], arcs[k,1]]
|
||||
).ToArray().Sum();
|
||||
|
||||
solver.Add(s1 == s2);
|
||||
|
||||
}
|
||||
|
||||
// Sanity check: just arcs with connections can have a flow.
|
||||
foreach(int i in NODES) {
|
||||
foreach(int j in NODES) {
|
||||
if (mat[i,j] == 0) {
|
||||
solver.Add(flow[i,j] == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = z.Maximize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(flow.Flatten(),
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("z: {0}",z.Value());
|
||||
foreach(int i in NODES) {
|
||||
foreach(int j in NODES) {
|
||||
Console.Write(flow[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
232
examples/dotnet/csharp/minesweeper.cs
Normal file
232
examples/dotnet/csharp/minesweeper.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
//
|
||||
// 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 Minesweeper
|
||||
{
|
||||
|
||||
static int X = -1;
|
||||
|
||||
//
|
||||
// Default problem.
|
||||
// It has 4 solutions.
|
||||
//
|
||||
static int default_r = 8;
|
||||
static int default_c = 8;
|
||||
static int[,] default_game = {{2, 3, X, 2, 2, X, 2, 1},
|
||||
{X, X, 4, X, X, 4, X, 2},
|
||||
{X, X, X, X, X, X, 4, X},
|
||||
{X, 5, X, 6, X, X, X, 2},
|
||||
{2, X, X, X, 5, 5, X, 2},
|
||||
{1, 3, 4, X, X, X, 4, X},
|
||||
{0, 1, X, 4, X, X, X, 3},
|
||||
{0, 1, 2, X, 2, 3, X, 2}};
|
||||
|
||||
// for the actual problem
|
||||
static int r;
|
||||
static int c;
|
||||
static int[,] game;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves the Minesweeper problems.
|
||||
*
|
||||
* See http://www.hakank.org/google_or_tools/minesweeper.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Minesweeper");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int[] S = {-1, 0, 1};
|
||||
|
||||
Console.WriteLine("Problem:");
|
||||
for(int i = 0; i < r; i++) {
|
||||
for(int j = 0; j < c; j++) {
|
||||
if (game[i,j] > X) {
|
||||
Console.Write(game[i,j] + " ");
|
||||
} else {
|
||||
Console.Write("X ");
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] mines = solver.MakeIntVarMatrix(r, c, 0, 1, "mines");
|
||||
// for branching
|
||||
IntVar[] mines_flat = mines.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < r; i++) {
|
||||
for(int j = 0; j < c; j++) {
|
||||
if (game[i,j] >= 0) {
|
||||
solver.Add( mines[i,j] == 0);
|
||||
|
||||
// this cell is the sum of all its neighbours
|
||||
var tmp = from a in S from b in S where
|
||||
i + a >= 0 &&
|
||||
j + b >= 0 &&
|
||||
i + a < r &&
|
||||
j + b < c
|
||||
select(mines[i+a,j+b]);
|
||||
|
||||
solver.Add(tmp.ToArray().Sum() == game[i,j]);
|
||||
|
||||
}
|
||||
|
||||
if (game[i,j] > X) {
|
||||
// This cell cannot be a mine since it
|
||||
// has some value assigned to it
|
||||
solver.Add(mines[i,j] == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(mines_flat,
|
||||
Solver.CHOOSE_PATH,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int sol = 0;
|
||||
while (solver.NextSolution()) {
|
||||
sol++;
|
||||
Console.WriteLine("Solution #{0} ", sol + " ");
|
||||
for(int i = 0; i < r; i++) {
|
||||
for(int j = 0; j < c; j++){
|
||||
Console.Write("{0} ", mines[i,j].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Reads a minesweeper file.
|
||||
* File format:
|
||||
* # a comment which is ignored
|
||||
* % a comment which also is ignored
|
||||
* number of rows
|
||||
* number of columns
|
||||
* <
|
||||
* row number of neighbours lines...
|
||||
* >
|
||||
*
|
||||
* 0..8 means number of neighbours, "." mean unknown (may be a mine)
|
||||
*
|
||||
* Example (from minesweeper0.txt)
|
||||
* # Problem from Gecode/examples/minesweeper.cc problem 0
|
||||
* 6
|
||||
* 6
|
||||
* ..2.3.
|
||||
* 2.....
|
||||
* ..24.3
|
||||
* 1.34..
|
||||
* .....3
|
||||
* .3.3..
|
||||
*
|
||||
*/
|
||||
private static void readFile(String file) {
|
||||
|
||||
Console.WriteLine("readFile(" + file + ")");
|
||||
int lineCount = 0;
|
||||
|
||||
TextReader inr = new StreamReader(file);
|
||||
String str;
|
||||
while ((str = inr.ReadLine()) != null && str.Length > 0) {
|
||||
|
||||
str = str.Trim();
|
||||
|
||||
// ignore comments
|
||||
if(str.StartsWith("#") || str.StartsWith("%")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine(str);
|
||||
if (lineCount == 0) {
|
||||
r = Convert.ToInt32(str); // number of rows
|
||||
} else if (lineCount == 1) {
|
||||
c = Convert.ToInt32(str); // number of columns
|
||||
game = new int[r,c];
|
||||
} else {
|
||||
// the problem matrix
|
||||
String[] row = Regex.Split(str, "");
|
||||
for(int j = 1; j <= c; j++) {
|
||||
String s = row[j];
|
||||
if (s.Equals(".")) {
|
||||
game[lineCount-2,j-1] = -1;
|
||||
} else {
|
||||
game[lineCount-2,j-1] = Convert.ToInt32(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lineCount++;
|
||||
|
||||
} // end while
|
||||
|
||||
inr.Close();
|
||||
|
||||
} // end readFile
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
String file = "";
|
||||
if (args.Length > 0) {
|
||||
file = args[0];
|
||||
readFile(file);
|
||||
} else {
|
||||
game = default_game;
|
||||
r = default_r;
|
||||
c = default_c;
|
||||
}
|
||||
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
136
examples/dotnet/csharp/mr_smith.cs
Normal file
136
examples/dotnet/csharp/mr_smith.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class MrSmith
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Mr Smith problem.
|
||||
*
|
||||
* From an IF Prolog example (http://www.ifcomputer.de/)
|
||||
* """
|
||||
* The Smith family and their three children want to pay a visit but they
|
||||
* do not all have the time to do so. Following are few hints who will go
|
||||
* and who will not:
|
||||
* o If Mr Smith comes, his wife will come too.
|
||||
* o At least one of their two sons Matt and John will come.
|
||||
* o Either Mrs Smith or Tim will come, but not both.
|
||||
* o Either Tim and John will come, or neither will come.
|
||||
* o If Matt comes, then John and his father will
|
||||
* also come.
|
||||
* """
|
||||
*
|
||||
* The answer should be:
|
||||
* Mr_Smith_comes = 0
|
||||
* Mrs_Smith_comes = 0
|
||||
* Matt_comes = 0
|
||||
* John_comes = 1
|
||||
* Tim_comes = 1
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/mr_smith.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("MrSmith");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 5;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x");
|
||||
IntVar Mr_Smith = x[0];
|
||||
IntVar Mrs_Smith = x[1];
|
||||
IntVar Matt = x[2];
|
||||
IntVar John = x[3];
|
||||
IntVar Tim = x[4];
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
//
|
||||
// I've kept the MiniZinc constraints for clarity
|
||||
// and debugging.
|
||||
//
|
||||
|
||||
// If Mr Smith comes then his wife will come too.
|
||||
// (Mr_Smith -> Mrs_Smith)
|
||||
solver.Add(Mr_Smith - Mrs_Smith <= 0);
|
||||
|
||||
// At least one of their two sons Matt and John will come.
|
||||
// (Matt \/ John)
|
||||
solver.Add(Matt+John >= 1);
|
||||
|
||||
// Either Mrs Smith or Tim will come but not both.
|
||||
// bool2int(Mrs_Smith) + bool2int(Tim) = 1
|
||||
// (Mrs_Smith xor Tim)
|
||||
solver.Add(Mrs_Smith + Tim == 1);
|
||||
|
||||
// Either Tim and John will come or neither will come.
|
||||
// (Tim = John)
|
||||
solver.Add(Tim == John);
|
||||
|
||||
// If Matt comes /\ then John and his father will also come.
|
||||
// (Matt -> (John /\ Mr_Smith))
|
||||
solver.Add(Matt - (John*Mr_Smith) <= 0);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
Console.WriteLine("Mr Smith : {0}", Mr_Smith.Value());
|
||||
Console.WriteLine("Mrs Smith: {0}", Mrs_Smith.Value());
|
||||
Console.WriteLine("Matt : {0}", Matt.Value());
|
||||
Console.WriteLine("John : {0}", John.Value());
|
||||
Console.WriteLine("Tim : {0}", Tim.Value());
|
||||
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
210
examples/dotnet/csharp/nontransitive_dice.cs
Normal file
210
examples/dotnet/csharp/nontransitive_dice.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class NonTransitiveDice
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Nontransitive dice.
|
||||
*
|
||||
* From
|
||||
* http://en.wikipedia.org/wiki/Nontransitive_dice
|
||||
* """
|
||||
* A set of nontransitive dice is a set of dice for which the relation
|
||||
* 'is more likely to roll a higher number' is not transitive. See also
|
||||
* intransitivity.
|
||||
*
|
||||
* This situation is similar to that in the game Rock, Paper, Scissors,
|
||||
* in which each element has an advantage over one choice and a
|
||||
* disadvantage to the other.
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/nontransitive_dice.py
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static void Solve(int m=3, int n=6, int minimize_val=0)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Nontransitive_dice");
|
||||
|
||||
Console.WriteLine("Number of dice: {0}", m);
|
||||
Console.WriteLine("Number of sides: {0}", n);
|
||||
Console.WriteLine("minimize_val: {0}\n", minimize_val);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
// The dice
|
||||
IntVar[,] dice = solver.MakeIntVarMatrix(m, n, 1, n*2, "dice");
|
||||
IntVar[] dice_flat = dice.Flatten();
|
||||
|
||||
// For comparison (probability)
|
||||
IntVar[,] comp = solver.MakeIntVarMatrix(m, 2, 0, n*n, "dice");
|
||||
IntVar[] comp_flat = comp.Flatten();
|
||||
|
||||
// For branching
|
||||
IntVar[] all = dice_flat.Concat(comp_flat).ToArray();
|
||||
|
||||
// The following variables are for summaries or objectives
|
||||
IntVar[] gap = solver.MakeIntVarArray(m, 0, n*n, "gap");
|
||||
IntVar gap_sum = gap.Sum().Var();
|
||||
|
||||
IntVar max_val = dice_flat.Max().Var();
|
||||
IntVar max_win = comp_flat.Max().Var();
|
||||
|
||||
// number of occurrences of each value of the dice
|
||||
IntVar[] counts = solver.MakeIntVarArray(n*2+1, 0, n*m, "counts");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// Number of occurrences for each number
|
||||
solver.Add(dice_flat.Distribute(counts));
|
||||
|
||||
// Order of the number of each die, lowest first
|
||||
for(int i = 0; i < m; i++) {
|
||||
for(int j = 0; j < n-1; j++) {
|
||||
solver.Add(dice[i,j] <= dice[i,j+1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Nontransitivity
|
||||
for(int i = 0; i < m; i++) {
|
||||
solver.Add(comp[i,0] > comp[i,1]);
|
||||
}
|
||||
|
||||
// Probability gap
|
||||
for(int i = 0; i < m; i++) {
|
||||
solver.Add(gap[i] == comp[i,0] - comp[i,1]);
|
||||
solver.Add(gap[i] > 0);
|
||||
}
|
||||
|
||||
// And now we roll...
|
||||
// comp[] is the number of wins for [A vs B, B vs A]
|
||||
for(int d = 0; d < m; d++) {
|
||||
IntVar sum1 = ( from r1 in Enumerable.Range(0, n)
|
||||
from r2 in Enumerable.Range(0, n)
|
||||
select (dice[d % m, r1] > dice[(d+1) % m, r2])
|
||||
).ToArray().Sum().Var();
|
||||
|
||||
solver.Add(comp[d%m,0] == sum1);
|
||||
|
||||
IntVar sum2 = ( from r1 in Enumerable.Range(0, n)
|
||||
from r2 in Enumerable.Range(0, n)
|
||||
select (dice[(d+1) % m, r1] > dice[d % m, r2])
|
||||
).ToArray().Sum().Var();
|
||||
|
||||
solver.Add(comp[d%m,1] == sum2);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
if (minimize_val > 0) {
|
||||
Console.WriteLine("Minimizing max_val");
|
||||
|
||||
OptimizeVar obj = max_val.Minimize(1);
|
||||
|
||||
// Other experiments:
|
||||
// OptimizeVar obj = max_win.Maximize(1);
|
||||
// OptimizeVar obj = gap_sum.Maximize(1);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
} else {
|
||||
solver.NewSearch(db);
|
||||
}
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("gap_sum: {0}", gap_sum.Value());
|
||||
Console.WriteLine("gap: {0}", (from i in Enumerable.Range(0, m)
|
||||
select gap[i].Value().ToString()
|
||||
).ToArray()
|
||||
);
|
||||
Console.WriteLine("max_val: {0}", max_val.Value());
|
||||
Console.WriteLine("max_win: {0}", max_win.Value());
|
||||
Console.WriteLine("dice:");
|
||||
for(int i = 0; i < m; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write(dice[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine("comp:");
|
||||
for(int i = 0; i < m; i++) {
|
||||
for(int j = 0; j < 2; j++) {
|
||||
Console.Write(comp[i,j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine("counts:");
|
||||
for(int i = 1; i < n*2+1; i++) {
|
||||
int c = (int)counts[i].Value();
|
||||
if (c > 0) {
|
||||
Console.Write("{0}({1}) ", i, c);
|
||||
}
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
}
|
||||
|
||||
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 m = 3; // number of dice
|
||||
int n = 6; // number of sides of each die
|
||||
int minimize_val = 0; // minimizing max_max (0: no, 1: yes)
|
||||
|
||||
if (args.Length > 0) {
|
||||
m = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (args.Length > 1) {
|
||||
n = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
if (args.Length > 2) {
|
||||
minimize_val = Convert.ToInt32(args[2]);
|
||||
}
|
||||
|
||||
Solve(m, n, minimize_val);
|
||||
}
|
||||
}
|
||||
119
examples/dotnet/csharp/nqueens.cs
Normal file
119
examples/dotnet/csharp/nqueens.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class NQueens
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solves the N-Queens problem.
|
||||
*
|
||||
* Syntax: nqueens.exe n num print
|
||||
* where
|
||||
* n : size of board
|
||||
* num : number of solutions to calculate
|
||||
* print: print the results (if > 0)
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n=8, int num=0, int print=1)
|
||||
{
|
||||
Solver solver = new Solver("N-Queens");
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] q = solver.MakeIntVarArray(n, 0, n-1, "q");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(q.AllDifferent());
|
||||
|
||||
IntVar[] q1 = new IntVar[n];
|
||||
IntVar[] q2 = new IntVar[n];
|
||||
for(int i = 0; i < n; i++) {
|
||||
q1[i] = (q[i] + i).Var();
|
||||
q2[i] = (q[i] - i).Var();
|
||||
}
|
||||
solver.Add(q1.AllDifferent());
|
||||
solver.Add(q2.AllDifferent());
|
||||
|
||||
// Alternative version: it works as well but are not that clear
|
||||
/*
|
||||
solver.Add((from i in Enumerable.Range(0, n)
|
||||
select (q[i] + i).Var()).ToArray().AllDifferent());
|
||||
|
||||
solver.Add((from i in Enumerable.Range(0, n)
|
||||
select (q[i] - i).Var()).ToArray().AllDifferent());
|
||||
*/
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(q,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MAX,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
int c = 0;
|
||||
while (solver.NextSolution()) {
|
||||
if (print > 0) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0} ", q[i].Value());
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
c++;
|
||||
if (num > 0 && c >= num) {
|
||||
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 = 8;
|
||||
int num = 0;
|
||||
int print = 1;
|
||||
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (args.Length > 1) {
|
||||
num = Convert.ToInt32(args[1]);
|
||||
}
|
||||
if (args.Length > 2) {
|
||||
print = Convert.ToInt32(args[2]);
|
||||
}
|
||||
|
||||
Console.WriteLine("n: {0} num: {1} print: {2}", n, num, print);
|
||||
|
||||
Solve(n, num, print);
|
||||
}
|
||||
}
|
||||
323
examples/dotnet/csharp/nurse_rostering_regular.cs
Normal file
323
examples/dotnet/csharp/nurse_rostering_regular.cs
Normal file
@@ -0,0 +1,323 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class NurseRostering
|
||||
{
|
||||
|
||||
|
||||
/*
|
||||
* Global constraint regular
|
||||
*
|
||||
* This is a translation of MiniZinc's regular constraint (defined in
|
||||
* lib/zinc/globals.mzn), via the Comet code refered above.
|
||||
* All comments are from the MiniZinc code.
|
||||
* """
|
||||
* The sequence of values in array 'x' (which must all be in the range 1..S)
|
||||
* is accepted by the DFA of 'Q' states with input 1..S and transition
|
||||
* function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'
|
||||
* (which must be in 1..Q) and accepting states 'F' (which all must be in
|
||||
* 1..Q). We reserve state 0 to be an always failing state.
|
||||
* """
|
||||
*
|
||||
* x : IntVar array
|
||||
* Q : number of states
|
||||
* S : input_max
|
||||
* d : transition matrix
|
||||
* q0: initial state
|
||||
* F : accepting states
|
||||
*
|
||||
*/
|
||||
static void MyRegular(Solver solver,
|
||||
IntVar[] x,
|
||||
int Q,
|
||||
int S,
|
||||
int[,] d,
|
||||
int q0,
|
||||
int[] F) {
|
||||
|
||||
|
||||
|
||||
Debug.Assert(Q > 0, "regular: 'Q' must be greater than zero");
|
||||
Debug.Assert(S > 0, "regular: 'S' must be greater than zero");
|
||||
|
||||
// d2 is the same as d, except we add one extra transition for
|
||||
// each possible input; each extra transition is from state zero
|
||||
// to state zero. This allows us to continue even if we hit a
|
||||
// non-accepted input.
|
||||
int[][] d2 = new int[Q+1][];
|
||||
for(int i = 0; i <= Q; i++) {
|
||||
int[] row = new int[S];
|
||||
for(int j = 0; j < S; j++) {
|
||||
if (i == 0) {
|
||||
row[j] = 0;
|
||||
} else {
|
||||
row[j] = d[i-1,j];
|
||||
}
|
||||
}
|
||||
d2[i] = row;
|
||||
}
|
||||
|
||||
int[] d2_flatten = (from i in Enumerable.Range(0, Q+1)
|
||||
from j in Enumerable.Range(0, S)
|
||||
select d2[i][j]).ToArray();
|
||||
|
||||
// If x has index set m..n, then a[m-1] holds the initial state
|
||||
// (q0), and a[i+1] holds the state we're in after processing
|
||||
// x[i]. If a[n] is in F, then we succeed (ie. accept the
|
||||
// string).
|
||||
int m = 0;
|
||||
int n = x.Length;
|
||||
|
||||
IntVar[] a = solver.MakeIntVarArray(n+1-m, 0,Q+1, "a");
|
||||
// Check that the final state is in F
|
||||
solver.Add(a[a.Length-1].Member(F));
|
||||
// First state is q0
|
||||
solver.Add(a[m] == q0);
|
||||
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add(x[i] >= 1);
|
||||
solver.Add(x[i] <= S);
|
||||
// Determine a[i+1]: a[i+1] == d2[a[i], x[i]]
|
||||
solver.Add(a[i+1] == d2_flatten.Element(((a[i])*S)+(x[i]-1)));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Nurse rostering
|
||||
*
|
||||
* This is a simple nurse rostering model using a DFA and
|
||||
* my decomposition of regular constraint.
|
||||
*
|
||||
* The DFA is from MiniZinc Tutorial, Nurse Rostering example:
|
||||
* - one day off every 4 days
|
||||
* - no 3 nights in a row.
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/nurse_rostering.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("NurseRostering");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
|
||||
// Note: If you change num_nurses or num_days,
|
||||
// please also change the constraints
|
||||
// on nurse_stat and/or day_stat.
|
||||
int num_nurses = 7;
|
||||
int num_days = 14;
|
||||
|
||||
// Note: I had to add a dummy shift.
|
||||
int dummy_shift = 0;
|
||||
int day_shift = 1;
|
||||
int night_shift = 2;
|
||||
int off_shift = 3;
|
||||
int[] shifts = {dummy_shift, day_shift, night_shift, off_shift};
|
||||
int[] valid_shifts = {day_shift, night_shift, off_shift};
|
||||
|
||||
// the DFA (for regular)
|
||||
int n_states = 6;
|
||||
int input_max = 3;
|
||||
int initial_state = 1; // 0 is for the failing state
|
||||
int[] accepting_states = {1,2,3,4,5,6};
|
||||
|
||||
int[,] transition_fn = {
|
||||
// d,n,o
|
||||
{2,3,1}, // state 1
|
||||
{4,4,1}, // state 2
|
||||
{4,5,1}, // state 3
|
||||
{6,6,1}, // state 4
|
||||
{6,0,1}, // state 5
|
||||
{0,0,1} // state 6
|
||||
};
|
||||
|
||||
string[] days = {"d","n","o"}; // for presentation
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
// For regular
|
||||
IntVar[,] x =
|
||||
solver.MakeIntVarMatrix(num_nurses, num_days, valid_shifts, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
// summary of the nurses
|
||||
IntVar[] nurse_stat =
|
||||
solver.MakeIntVarArray(num_nurses, 0, num_days, "nurse_stat");
|
||||
|
||||
// summary of the shifts per day
|
||||
int num_shifts = shifts.Length;
|
||||
IntVar[,] day_stat = new IntVar[num_days, num_shifts];
|
||||
for(int i = 0; i < num_days; i++) {
|
||||
for(int j = 0; j < num_shifts; j++) {
|
||||
day_stat[i,j] = solver.MakeIntVar(0, num_nurses, "day_stat");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < num_nurses; i++) {
|
||||
IntVar[] reg_input = new IntVar[num_days];
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
reg_input[j] = x[i,j];
|
||||
}
|
||||
MyRegular(solver, reg_input, n_states, input_max, transition_fn,
|
||||
initial_state, accepting_states);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Statistics and constraints for each nurse
|
||||
//
|
||||
for(int i = 0; i < num_nurses; i++) {
|
||||
|
||||
// Number of worked days (either day or night shift)
|
||||
IntVar[] b = new IntVar[num_days];
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
b[j] = ((x[i,j] == day_shift) + (x[i,j] == night_shift)).Var();
|
||||
}
|
||||
solver.Add(b.Sum() == nurse_stat[i]);
|
||||
|
||||
// Each nurse must work between 7 and 10
|
||||
// days/nights during this period
|
||||
solver.Add(nurse_stat[i] >= 7);
|
||||
solver.Add(nurse_stat[i] <= 10);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Statistics and constraints for each day
|
||||
//
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
for(int t = 0; t < num_shifts; t++) {
|
||||
IntVar[] b = new IntVar[num_nurses];
|
||||
for(int i = 0; i < num_nurses; i++) {
|
||||
b[i] = x[i,j] == t;
|
||||
}
|
||||
solver.Add(b.Sum() == day_stat[j,t]);
|
||||
}
|
||||
|
||||
//
|
||||
// Some constraints for each day:
|
||||
//
|
||||
// Note: We have a strict requirements of
|
||||
// the number of shifts.
|
||||
// Using atleast constraints is harder
|
||||
// in this model.
|
||||
//
|
||||
if (j % 7 == 5 || j % 7 == 6) {
|
||||
// special constraints for the weekends
|
||||
solver.Add(day_stat[j,day_shift] == 2);
|
||||
solver.Add(day_stat[j,night_shift] == 1);
|
||||
solver.Add(day_stat[j,off_shift] == 4 );
|
||||
} else {
|
||||
// for workdays:
|
||||
|
||||
// - exactly 3 on day shift
|
||||
solver.Add(day_stat[j,day_shift] == 3);
|
||||
// - exactly 2 on night
|
||||
solver.Add(day_stat[j,night_shift] == 2);
|
||||
// - exactly 2 off duty
|
||||
solver.Add(day_stat[j,off_shift] == 2 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int num_solutions = 0;
|
||||
while (solver.NextSolution()) {
|
||||
num_solutions++;
|
||||
for(int i = 0; i < num_nurses; i++) {
|
||||
Console.Write("Nurse #{0,-2}: ", i);
|
||||
var occ = new Dictionary<int, int>();
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
int v = (int)x[i,j].Value()-1;
|
||||
if (!occ.ContainsKey(v)) {
|
||||
occ[v] = 0;
|
||||
}
|
||||
occ[v]++;
|
||||
Console.Write(days[v] + " ");
|
||||
}
|
||||
|
||||
Console.Write(" #workdays: {0,2}", nurse_stat[i].Value());
|
||||
foreach(int s in valid_shifts) {
|
||||
int v = 0;
|
||||
if (occ.ContainsKey(s-1)) {
|
||||
v = occ[s-1];
|
||||
}
|
||||
Console.Write(" {0}:{1}", days[s-1], v);
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Statistics per day:\nDay d n o");
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
Console.Write("Day #{0,2}: ", j);
|
||||
foreach(int t in valid_shifts) {
|
||||
Console.Write(day_stat[j,t].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
// We just show 2 solutions
|
||||
if (num_solutions > 1) {
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
286
examples/dotnet/csharp/nurse_rostering_transition.cs
Normal file
286
examples/dotnet/csharp/nurse_rostering_transition.cs
Normal file
@@ -0,0 +1,286 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class NurseRostering
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Nurse rostering
|
||||
*
|
||||
* This is a simple nurse rostering model using a DFA and
|
||||
* the built-in TransitionConstraint.
|
||||
*
|
||||
* The DFA is from MiniZinc Tutorial, Nurse Rostering example:
|
||||
* - one day off every 4 days
|
||||
* - no 3 nights in a row.
|
||||
*
|
||||
* Also see:
|
||||
* - http://www.hakank.org/or-tools/nurse_rostering.py
|
||||
* - http://www.hakank.org/or-tools/nurse_rostering_regular.cs
|
||||
* which use (a decomposition of) regular constraint
|
||||
*
|
||||
*/
|
||||
private static void Solve(int nurse_multiplier, int week_multiplier)
|
||||
{
|
||||
Console.WriteLine("Starting Nurse Rostering");
|
||||
Console.WriteLine(" - {0} teams of 7 nurses", nurse_multiplier);
|
||||
Console.WriteLine(" - {0} blocks of 14 days", week_multiplier);
|
||||
|
||||
Solver solver = new Solver("NurseRostering");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
|
||||
// Note: If you change num_nurses or num_days,
|
||||
// please also change the constraints
|
||||
// on nurse_stat and/or day_stat.
|
||||
int num_nurses = 7 * nurse_multiplier;
|
||||
int num_days = 14 * week_multiplier;
|
||||
|
||||
// Note: I had to add a dummy shift.
|
||||
int dummy_shift = 0;
|
||||
int day_shift = 1;
|
||||
int night_shift = 2;
|
||||
int off_shift = 3;
|
||||
int[] shifts = {dummy_shift, day_shift, night_shift, off_shift};
|
||||
int[] valid_shifts = {day_shift, night_shift, off_shift};
|
||||
|
||||
// the DFA (for regular)
|
||||
int initial_state = 1;
|
||||
int[] accepting_states = {1,2,3,4,5,6};
|
||||
|
||||
/*
|
||||
// This is the transition function
|
||||
// used in nurse_rostering_regular.cs
|
||||
int[,] transition_fn = {
|
||||
// d,n,o
|
||||
{2,3,1}, // state 1
|
||||
{4,4,1}, // state 2
|
||||
{4,5,1}, // state 3
|
||||
{6,6,1}, // state 4
|
||||
{6,0,1}, // state 5
|
||||
{0,0,1} // state 6
|
||||
};
|
||||
*/
|
||||
|
||||
// For TransitionConstraint
|
||||
IntTupleSet transition_tuples = new IntTupleSet(3);
|
||||
// state, input, next state
|
||||
transition_tuples.InsertAll(new int[,] { {1,1,2},
|
||||
{1,2,3},
|
||||
{1,3,1},
|
||||
{2,1,4},
|
||||
{2,2,4},
|
||||
{2,3,1},
|
||||
{3,1,4},
|
||||
{3,2,5},
|
||||
{3,3,1},
|
||||
{4,1,6},
|
||||
{4,2,6},
|
||||
{4,3,1},
|
||||
{5,1,6},
|
||||
{5,3,1},
|
||||
{6,3,1} });
|
||||
|
||||
string[] days = {"d","n","o"}; // for presentation
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
//
|
||||
// For TransitionConstraint
|
||||
//
|
||||
IntVar[,] x =
|
||||
solver.MakeIntVarMatrix(num_nurses, num_days, valid_shifts, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
//
|
||||
// summary of the nurses
|
||||
//
|
||||
IntVar[] nurse_stat = new IntVar[num_nurses];
|
||||
|
||||
//
|
||||
// summary of the shifts per day
|
||||
//
|
||||
int num_shifts = shifts.Length;
|
||||
IntVar[,] day_stat = new IntVar[num_days, num_shifts];
|
||||
for(int i = 0; i < num_days; i++) {
|
||||
for(int j = 0; j < num_shifts; j++) {
|
||||
day_stat[i,j] = solver.MakeIntVar(0, num_nurses, "day_stat");
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < num_nurses; i++) {
|
||||
IntVar[] reg_input = new IntVar[num_days];
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
reg_input[j] = x[i,j];
|
||||
}
|
||||
|
||||
solver.Add(reg_input.Transition(transition_tuples,
|
||||
initial_state,
|
||||
accepting_states));
|
||||
}
|
||||
|
||||
//
|
||||
// Statistics and constraints for each nurse
|
||||
//
|
||||
for(int nurse = 0; nurse < num_nurses; nurse++) {
|
||||
|
||||
// Number of worked days (either day or night shift)
|
||||
IntVar[] nurse_days = new IntVar[num_days];
|
||||
for(int day = 0; day < num_days; day++) {
|
||||
nurse_days[day] =
|
||||
x[nurse, day].IsMember(new int[] { day_shift, night_shift });
|
||||
}
|
||||
nurse_stat[nurse] = nurse_days.Sum().Var();
|
||||
|
||||
// Each nurse must work between 7 and 10
|
||||
// days/nights during this period
|
||||
solver.Add(nurse_stat[nurse] >= 7 * week_multiplier / nurse_multiplier);
|
||||
solver.Add(nurse_stat[nurse] <= 10 * week_multiplier / nurse_multiplier);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// Statistics and constraints for each day
|
||||
//
|
||||
for(int day = 0; day < num_days; day++) {
|
||||
IntVar[] nurses = new IntVar[num_nurses];
|
||||
for(int nurse = 0; nurse < num_nurses; nurse++) {
|
||||
nurses[nurse] = x[nurse, day];
|
||||
}
|
||||
IntVar[] stats = new IntVar[num_shifts];
|
||||
for (int shift = 0; shift < num_shifts; ++shift)
|
||||
{
|
||||
stats[shift] = day_stat[day, shift];
|
||||
}
|
||||
solver.Add(nurses.Distribute(stats));
|
||||
|
||||
//
|
||||
// Some constraints for each day:
|
||||
//
|
||||
// Note: We have a strict requirements of
|
||||
// the number of shifts.
|
||||
// Using atleast constraints is harder
|
||||
// in this model.
|
||||
//
|
||||
if (day % 7 == 5 || day % 7 == 6) {
|
||||
// special constraints for the weekends
|
||||
solver.Add(day_stat[day, day_shift] == 2 * nurse_multiplier);
|
||||
solver.Add(day_stat[day, night_shift] == nurse_multiplier);
|
||||
solver.Add(day_stat[day, off_shift] == 4 * nurse_multiplier);
|
||||
} else {
|
||||
// for workdays:
|
||||
|
||||
// - exactly 3 on day shift
|
||||
solver.Add(day_stat[day, day_shift] == 3 * nurse_multiplier);
|
||||
// - exactly 2 on night
|
||||
solver.Add(day_stat[day, night_shift] == 2 * nurse_multiplier);
|
||||
// - exactly 2 off duty
|
||||
solver.Add(day_stat[day, off_shift] == 2 * nurse_multiplier);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
SearchMonitor log = solver.MakeSearchLog(1000000);
|
||||
|
||||
solver.NewSearch(db, log);
|
||||
|
||||
int num_solutions = 0;
|
||||
while (solver.NextSolution()) {
|
||||
num_solutions++;
|
||||
for(int i = 0; i < num_nurses; i++) {
|
||||
Console.Write("Nurse #{0,-2}: ", i);
|
||||
var occ = new Dictionary<int, int>();
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
int v = (int)x[i,j].Value()-1;
|
||||
if (!occ.ContainsKey(v)) {
|
||||
occ[v] = 0;
|
||||
}
|
||||
occ[v]++;
|
||||
Console.Write(days[v] + " ");
|
||||
}
|
||||
|
||||
Console.Write(" #workdays: {0,2}", nurse_stat[i].Value());
|
||||
foreach(int s in valid_shifts) {
|
||||
int v = 0;
|
||||
if (occ.ContainsKey(s-1)) {
|
||||
v = occ[s-1];
|
||||
}
|
||||
Console.Write(" {0}:{1}", days[s-1], v);
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
Console.WriteLine("Statistics per day:\nDay d n o");
|
||||
for(int j = 0; j < num_days; j++) {
|
||||
Console.Write("Day #{0,2}: ", j);
|
||||
foreach(int t in valid_shifts) {
|
||||
Console.Write(day_stat[j,t].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
// We just show 2 solutions
|
||||
if (num_solutions > 1) {
|
||||
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 nurse_multiplier = 1;
|
||||
int week_multiplier = 1;
|
||||
if (args.Length > 0) {
|
||||
nurse_multiplier = Convert.ToInt32(args[0]);
|
||||
}
|
||||
if (args.Length > 1) {
|
||||
week_multiplier = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
Solve(nurse_multiplier, week_multiplier);
|
||||
}
|
||||
}
|
||||
219
examples/dotnet/csharp/nurses_sat.cs
Normal file
219
examples/dotnet/csharp/nurses_sat.cs
Normal file
@@ -0,0 +1,219 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.Sat;
|
||||
|
||||
public class NurseSolutionObserver : CpSolverSolutionCallback
|
||||
{
|
||||
public NurseSolutionObserver(IntVar[,,] shifts, int num_nurses, int num_days,
|
||||
int num_shifts, HashSet<int> to_print) {
|
||||
shifts_ = shifts;
|
||||
num_nurses_ = num_nurses;
|
||||
num_days_ = num_days;
|
||||
num_shifts_ = num_shifts;
|
||||
to_print_ = to_print;
|
||||
}
|
||||
|
||||
public override void OnSolutionCallback()
|
||||
{
|
||||
solution_count_++;
|
||||
if (to_print_.Contains(solution_count_))
|
||||
{
|
||||
Console.WriteLine(
|
||||
String.Format("Solution #{0}: time = {1:.02} s",
|
||||
solution_count_, WallTime()));
|
||||
for (int d = 0; d < num_days_; ++d)
|
||||
{
|
||||
Console.WriteLine(String.Format("Day #{0}", d));
|
||||
for (int n = 0; n < num_nurses_; ++n)
|
||||
{
|
||||
for (int s = 0; s < num_shifts_; ++s)
|
||||
{
|
||||
if (BooleanValue(shifts_[n, d, s]))
|
||||
{
|
||||
Console.WriteLine(
|
||||
String.Format(" Nurse #{0} is working shift #{1}", n, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int SolutionCount()
|
||||
{
|
||||
return solution_count_;
|
||||
}
|
||||
|
||||
private int solution_count_;
|
||||
private IntVar[,,] shifts_;
|
||||
private int num_nurses_;
|
||||
private int num_days_;
|
||||
private int num_shifts_;
|
||||
private HashSet<int> to_print_;
|
||||
}
|
||||
|
||||
public class NursesSat
|
||||
{
|
||||
static void Solve()
|
||||
{
|
||||
// Data.
|
||||
int num_nurses = 4;
|
||||
// Nurse assigned to shift 0 means not working that day.
|
||||
int num_shifts = 4;
|
||||
int num_days = 7;
|
||||
|
||||
var all_nurses = Enumerable.Range(0, num_nurses);
|
||||
var all_shifts = Enumerable.Range(0, num_shifts);
|
||||
var all_working_shifts = Enumerable.Range(1, num_shifts - 1);
|
||||
var all_days = Enumerable.Range(0, num_days);
|
||||
|
||||
// Creates the model.
|
||||
CpModel model = new CpModel();
|
||||
|
||||
// Creates shift variables.
|
||||
// shift[n, d, s]: nurse "n" works shift "s" on day "d".
|
||||
IntVar[,,] shift = new IntVar[num_nurses, num_days, num_shifts];
|
||||
foreach (int n in all_nurses)
|
||||
{
|
||||
foreach (int d in all_days)
|
||||
{
|
||||
foreach (int s in all_shifts)
|
||||
{
|
||||
shift[n, d, s] =
|
||||
model.NewBoolVar(String.Format("shift_n{0}d{1}s{2}", n, d, s));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Makes assignments different on each day, that is each shift is
|
||||
// assigned at most one nurse. As we have the same number of
|
||||
// nurses and shifts, then each day, each shift is assigned to
|
||||
// exactly one nurse.
|
||||
foreach (int d in all_days)
|
||||
{
|
||||
foreach (int s in all_shifts)
|
||||
{
|
||||
IntVar[] tmp = new IntVar[num_nurses];
|
||||
foreach (int n in all_nurses)
|
||||
{
|
||||
tmp[n] = shift[n, d, s];
|
||||
}
|
||||
model.Add(tmp.Sum() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Nurses do 1 shift per day.
|
||||
foreach (int n in all_nurses)
|
||||
{
|
||||
foreach (int d in all_days)
|
||||
{
|
||||
IntVar[] tmp = new IntVar[num_shifts];
|
||||
foreach (int s in all_shifts)
|
||||
{
|
||||
tmp[s] = shift[n, d, s];
|
||||
}
|
||||
model.Add(tmp.Sum() == 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Each nurse works 5 or 6 days in a week.
|
||||
// That is each nurse works shift 0 at most 2 times.
|
||||
foreach (int n in all_nurses)
|
||||
{
|
||||
IntVar[] tmp = new IntVar[num_days];
|
||||
foreach (int d in all_days)
|
||||
{
|
||||
tmp[d] = shift[n, d, 0];
|
||||
}
|
||||
model.Add(1 <= tmp.Sum() <= 2);
|
||||
}
|
||||
|
||||
// works_shift[(n, s)] is 1 if nurse n works shift s at least one day in
|
||||
// the week.
|
||||
IntVar[,] works_shift = new IntVar[num_nurses, num_shifts];
|
||||
foreach (int n in all_nurses)
|
||||
{
|
||||
foreach (int s in all_shifts)
|
||||
{
|
||||
works_shift[n, s] =
|
||||
model.NewBoolVar(String.Format("works_shift_n{0}s{1}", n, s));
|
||||
IntVar[] tmp = new IntVar[num_days];
|
||||
foreach (int d in all_days)
|
||||
{
|
||||
tmp[d] = shift[n, d, s];
|
||||
}
|
||||
model.AddMaxEquality(works_shift[n, s], tmp);
|
||||
}
|
||||
}
|
||||
|
||||
// For each working shift, at most 2 nurses are assigned to that shift
|
||||
// during the week.
|
||||
foreach (int s in all_working_shifts)
|
||||
{
|
||||
IntVar[] tmp = new IntVar[num_nurses];
|
||||
foreach (int n in all_nurses)
|
||||
{
|
||||
tmp[n] = works_shift[n, s];
|
||||
}
|
||||
model.Add(tmp.Sum() <= 2);
|
||||
}
|
||||
|
||||
// If a nurse works shifts 2 or 3 on, she must also work that
|
||||
// shift the previous day or the following day. This means that
|
||||
// on a given day and shift, either she does not work that shift
|
||||
// on that day, or she works that shift on the day before, or the
|
||||
// day after.
|
||||
foreach (int n in all_nurses)
|
||||
{
|
||||
for (int s = 2; s <= 3; ++s)
|
||||
{
|
||||
foreach (int d in all_days)
|
||||
{
|
||||
int yesterday = d == 0 ? num_days - 1 : d - 1;
|
||||
int tomorrow = d == num_days - 1 ? 0 : d + 1;
|
||||
model.AddBoolOr(new ILiteral[] { shift[n, yesterday, s],
|
||||
shift[n, d, s].Not(),
|
||||
shift[n, tomorrow, s] } );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the solver and solve.
|
||||
CpSolver solver = new CpSolver();
|
||||
// Display a few solutions picked at random.
|
||||
HashSet<int> to_print = new HashSet<int>();
|
||||
to_print.Add(859);
|
||||
to_print.Add(2034);
|
||||
to_print.Add(5091);
|
||||
to_print.Add(7003);
|
||||
NurseSolutionObserver cb = new NurseSolutionObserver(
|
||||
shift, num_nurses, num_days, num_shifts, to_print);
|
||||
CpSolverStatus status = solver.SearchAllSolutions(model, cb);
|
||||
|
||||
// Statistics.
|
||||
Console.WriteLine("Statistics");
|
||||
Console.WriteLine(String.Format(" - solve status : {0}", status));
|
||||
Console.WriteLine(" - conflicts : " + solver.NumConflicts());
|
||||
Console.WriteLine(" - branches : " + solver.NumBranches());
|
||||
Console.WriteLine(" - wall time : " + solver.WallTime() + " ms");
|
||||
Console.WriteLine(" - #solutions : " + cb.SolutionCount());
|
||||
}
|
||||
|
||||
static void Main() {
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
137
examples/dotnet/csharp/olympic.cs
Normal file
137
examples/dotnet/csharp/olympic.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Olympic
|
||||
{
|
||||
|
||||
public static void minus(Solver solver,
|
||||
IntVar x,
|
||||
IntVar y,
|
||||
IntVar z)
|
||||
{
|
||||
solver.Add(z == (x - y).Abs());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Olympic puzzle.
|
||||
*
|
||||
* Benchmark for Prolog (BProlog)
|
||||
* """
|
||||
* File : olympic.pl
|
||||
* Author : Neng-Fa ZHOU
|
||||
* Date : 1993
|
||||
*
|
||||
* Purpose: solve a puzzle taken from Olympic Arithmetic Contest
|
||||
*
|
||||
* Given ten variables with the following configuration:
|
||||
*
|
||||
* X7 X8 X9 X10
|
||||
*
|
||||
* X4 X5 X6
|
||||
*
|
||||
* X2 X3
|
||||
*
|
||||
* X1
|
||||
*
|
||||
* We already know that X1 is equal to 3 and want to assign each variable
|
||||
* with a different integer from {1,2,...,10} such that for any three
|
||||
* variables
|
||||
* Xi Xj
|
||||
*
|
||||
* Xk
|
||||
*
|
||||
* the following constraint is satisfied:
|
||||
*
|
||||
* |Xi-Xj| = Xk
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/olympic.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("Olympic");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int n = 10;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x");
|
||||
IntVar X1 = x[0];
|
||||
IntVar X2 = x[1];
|
||||
IntVar X3 = x[2];
|
||||
IntVar X4 = x[3];
|
||||
IntVar X5 = x[4];
|
||||
IntVar X6 = x[5];
|
||||
IntVar X7 = x[6];
|
||||
IntVar X8 = x[7];
|
||||
IntVar X9 = x[8];
|
||||
IntVar X10 = x[9];
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
solver.Add(X1 == 3);
|
||||
minus(solver, X2, X3, X1);
|
||||
minus(solver, X4, X5, X2);
|
||||
minus(solver, X5, X6, X3);
|
||||
minus(solver, X7, X8, X4);
|
||||
minus(solver, X8, X9, X5);
|
||||
minus(solver, X9, X10, X6);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_SIMPLE,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write("{0,2} ", x[i].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
148
examples/dotnet/csharp/organize_day.cs
Normal file
148
examples/dotnet/csharp/organize_day.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// 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 OrganizeDay
|
||||
{
|
||||
|
||||
|
||||
//
|
||||
// No overlapping of tasks s1 and s2
|
||||
//
|
||||
public static void NoOverlap(Solver solver,
|
||||
IntVar s1, int d1,
|
||||
IntVar s2, int d2)
|
||||
{
|
||||
solver.Add((s1 + d1 <= s2) + (s2 + d2 <= s1) == 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Organizing a day.
|
||||
*
|
||||
* Simple scheduling problem.
|
||||
*
|
||||
* Problem formulation from ECLiPSe:
|
||||
* Slides on (Finite Domain) Constraint Logic Programming, page 38f
|
||||
* http://eclipseclp.org/reports/eclipse.ppt
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/google_or_tools/organize_day.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("OrganizeDay");
|
||||
|
||||
|
||||
int n = 4;
|
||||
|
||||
|
||||
int work = 0;
|
||||
int mail = 1;
|
||||
int shop = 2;
|
||||
int bank = 3;
|
||||
int[] tasks = {work, mail, shop, bank};
|
||||
int[] durations = {4,1,2,1};
|
||||
|
||||
// task [i,0] must be finished before task [i,1]
|
||||
int[,] before_tasks = {
|
||||
{bank, shop},
|
||||
{mail, work}
|
||||
};
|
||||
|
||||
// the valid times of the day
|
||||
int begin = 9;
|
||||
int end = 17;
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] begins = solver.MakeIntVarArray(n, begin, end, "begins");
|
||||
IntVar[] ends = solver.MakeIntVarArray(n, begin, end, "ends");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
foreach(int t in tasks) {
|
||||
solver.Add(ends[t] == begins[t] + durations[t]);
|
||||
}
|
||||
|
||||
foreach(int i in tasks) {
|
||||
foreach(int j in tasks) {
|
||||
if (i < j) {
|
||||
NoOverlap(solver,
|
||||
begins[i], durations[i],
|
||||
begins[j], durations[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// specific constraints
|
||||
for(int t = 0; t < before_tasks.GetLength(0); t++) {
|
||||
solver.Add(ends[before_tasks[t,0]] <= begins[before_tasks[t,1]]);
|
||||
}
|
||||
|
||||
solver.Add(begins[work] >= 11);
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(begins,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
foreach(int t in tasks) {
|
||||
Console.WriteLine("Task {0}: {1,2} .. ({2}) .. {3,2}",
|
||||
t,
|
||||
begins[t].Value(),
|
||||
durations[t],
|
||||
ends[t].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
124
examples/dotnet/csharp/organize_day_intervals.cs
Normal file
124
examples/dotnet/csharp/organize_day_intervals.cs
Normal file
@@ -0,0 +1,124 @@
|
||||
// Copyright 2010-2017 Google
|
||||
// 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 OrganizeDay
|
||||
{
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Organizing a day.
|
||||
*
|
||||
* Simple scheduling problem.
|
||||
*
|
||||
* Problem formulation from ECLiPSe:
|
||||
* Slides on (Finite Domain) Constraint Logic Programming, page 38f
|
||||
* http://eclipseclp.org/reports/eclipse.ppt
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/google_or_tools/organize_day.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("OrganizeDayIntervals");
|
||||
|
||||
|
||||
int n = 4;
|
||||
|
||||
|
||||
int work = 0;
|
||||
int mail = 1;
|
||||
int shop = 2;
|
||||
int bank = 3;
|
||||
// the valid times of the day
|
||||
int begin = 9;
|
||||
int end = 17;
|
||||
// tasks
|
||||
int[] tasks = {work, mail, shop, bank};
|
||||
// durations
|
||||
int[] durations = {4,1,2,1};
|
||||
// Arrays for interval variables.
|
||||
int[] starts_max = { begin,begin,begin,begin };
|
||||
int[] ends_max = { end -4, end - 1, end - 2, end - 1 };
|
||||
|
||||
// task [i,0] must be finished before task [i,1]
|
||||
int[,] before_tasks = {
|
||||
{bank, shop},
|
||||
{mail, work}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntervalVar[] intervals =
|
||||
solver.MakeFixedDurationIntervalVarArray(n,
|
||||
starts_max,
|
||||
ends_max,
|
||||
durations,
|
||||
false,
|
||||
"task");
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
DisjunctiveConstraint disjunctive = intervals.Disjunctive("Sequence");
|
||||
solver.Add(disjunctive);
|
||||
|
||||
// specific constraints
|
||||
for(int t = 0; t < before_tasks.GetLength(0); t++) {
|
||||
int before = before_tasks[t, 0];
|
||||
int after = before_tasks[t, 1];
|
||||
solver.Add(intervals[after].StartsAfterEnd(intervals[before]));
|
||||
}
|
||||
|
||||
solver.Add(intervals[work].StartsAfter(11));
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
SequenceVar var = disjunctive.SequenceVar();
|
||||
SequenceVar[] seq_array = new SequenceVar[] { var };
|
||||
DecisionBuilder db = solver.MakePhase(seq_array, Solver.SEQUENCE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
foreach(int t in tasks) {
|
||||
Console.WriteLine(intervals[t].ToString());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
137
examples/dotnet/csharp/p_median.cs
Normal file
137
examples/dotnet/csharp/p_median.cs
Normal file
@@ -0,0 +1,137 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class PMedian
|
||||
{
|
||||
/**
|
||||
*
|
||||
* P-median problem.
|
||||
*
|
||||
* Model and data from the OPL Manual, which describes the problem:
|
||||
* """
|
||||
* The P-Median problem is a well known problem in Operations Research.
|
||||
* The problem can be stated very simply, like this: given a set of customers
|
||||
* with known amounts of demand, a set of candidate locations for warehouses,
|
||||
* and the distance between each pair of customer-warehouse, choose P
|
||||
* warehouses to open that minimize the demand-weighted distance of serving
|
||||
* all customers from those P warehouses.
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/p_median.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("PMedian");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int p = 2;
|
||||
int num_customers = 4;
|
||||
IEnumerable<int> CUSTOMERS = Enumerable.Range(0, num_customers);
|
||||
|
||||
int num_warehouses = 3;
|
||||
IEnumerable<int> WAREHOUSES = Enumerable.Range(0, num_warehouses);
|
||||
|
||||
int[] demand = {100,80,80,70};
|
||||
int [,] distance = {
|
||||
{ 2, 10, 50},
|
||||
{ 2, 10, 52},
|
||||
{50, 60, 3},
|
||||
{40, 60, 1}
|
||||
};
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
IntVar[] open = solver.MakeIntVarArray(num_warehouses, 0, num_warehouses, "open");
|
||||
IntVar[,] ship = solver.MakeIntVarMatrix(num_customers, num_warehouses,
|
||||
0, 1, "ship");
|
||||
IntVar z = solver.MakeIntVar(0, 1000, "z");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
solver.Add((from c in CUSTOMERS
|
||||
from w in WAREHOUSES
|
||||
select (demand[c]*distance[c,w]*ship[c,w])
|
||||
).ToArray().Sum() == z);
|
||||
|
||||
solver.Add(open.Sum() == p);
|
||||
|
||||
foreach(int c in CUSTOMERS) {
|
||||
foreach(int w in WAREHOUSES) {
|
||||
solver.Add(ship[c,w] <= open[w]);
|
||||
}
|
||||
|
||||
solver.Add((from w in WAREHOUSES select ship[c,w]).ToArray().Sum() == 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = z.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(open.Concat(ship.Flatten()).ToArray(),
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("z: {0}",z.Value());
|
||||
Console.Write("open:");
|
||||
foreach(int w in WAREHOUSES) {
|
||||
Console.Write(open[w].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
foreach(int c in CUSTOMERS) {
|
||||
foreach(int w in WAREHOUSES) {
|
||||
Console.Write(ship[c,w].Value()+ " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
193
examples/dotnet/csharp/pandigital_numbers.cs
Normal file
193
examples/dotnet/csharp/pandigital_numbers.cs
Normal file
@@ -0,0 +1,193 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class PandigitalNumbers
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* toNum(solver, a, num, base)
|
||||
*
|
||||
* channelling between the array a and the number num.
|
||||
*
|
||||
*/
|
||||
private static Constraint ToNum(IntVar[] a,
|
||||
IntVar num,
|
||||
int bbase) {
|
||||
int len = a.Length;
|
||||
IntVar[] tmp = new IntVar[len];
|
||||
for(int i = 0; i < len; i++) {
|
||||
tmp[i] = (a[i]*(int)Math.Pow(bbase,len-i-1)).Var();
|
||||
}
|
||||
return tmp.Sum() == num;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Pandigital numbers in Google CP Solver.
|
||||
*
|
||||
* From Albert H. Beiler 'Recreations in the Theory of Numbers',
|
||||
* quoted from http://www.worldofnumbers.com/ninedig1.htm
|
||||
* """
|
||||
* Chapter VIII : Digits - and the magic of 9
|
||||
*
|
||||
* The following curious table shows how to arrange the 9 digits so that
|
||||
* the product of 2 groups is equal to a number represented by the
|
||||
* remaining digits.
|
||||
*
|
||||
* 12 x 483 = 5796
|
||||
* 42 x 138 = 5796
|
||||
* 18 x 297 = 5346
|
||||
* 27 x 198 = 5346
|
||||
* 39 x 186 = 7254
|
||||
* 48 x 159 = 7632
|
||||
* 28 x 157 = 4396
|
||||
* 4 x 1738 = 6952
|
||||
* 4 x 1963 = 7852
|
||||
* """
|
||||
*
|
||||
* Also see MathWorld http://mathworld.wolfram.com/PandigitalNumber.html
|
||||
* """
|
||||
* A number is said to be pandigital if it contains each of the digits
|
||||
* from 0 to 9 (and whose leading digit must be nonzero). However,
|
||||
* "zeroless" pandigital quantities contain the digits 1 through 9.
|
||||
* Sometimes exclusivity is also required so that each digit is
|
||||
* restricted to appear exactly once.
|
||||
* """
|
||||
*
|
||||
* Wikipedia: http://en.wikipedia.org/wiki/Pandigital_number
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/pandigital_numbers.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int bbase=10, int start=1, int len1=1, int len2=4)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("PandigitalNumbers");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int max_d = bbase-1;
|
||||
int x_len = max_d + 1 - start;
|
||||
int max_num = (int)Math.Pow(bbase,4)-1;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar num1 = solver.MakeIntVar(1, max_num, "num1");
|
||||
IntVar num2 = solver.MakeIntVar(1, max_num, "num2");
|
||||
IntVar res = solver.MakeIntVar(1, max_num, "res");
|
||||
|
||||
IntVar[] x = solver.MakeIntVarArray(x_len, start, max_d, "x");
|
||||
|
||||
// for labeling
|
||||
IntVar[] all = new IntVar[x_len+3];
|
||||
for(int i = 0; i < x_len; i++) {
|
||||
all[i] = x[i];
|
||||
}
|
||||
all[x_len] = num1;
|
||||
all[x_len+1] = num2;
|
||||
all[x_len+2] = res;
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
solver.Add(ToNum(( from i in Enumerable.Range(0, len1)
|
||||
select x[i]).ToArray(),
|
||||
num1,
|
||||
bbase));
|
||||
|
||||
solver.Add(ToNum(( from i in Enumerable.Range(len1, len2)
|
||||
select x[i]).ToArray(),
|
||||
num2,
|
||||
bbase));
|
||||
|
||||
solver.Add(ToNum(( from i in Enumerable.Range(len1+len2, x_len-(len1+len2))
|
||||
select x[i]).ToArray(),
|
||||
res,
|
||||
bbase));
|
||||
|
||||
|
||||
solver.Add(num1*num2 == res);
|
||||
|
||||
// no number must start with 0
|
||||
solver.Add(x[0] > 0);
|
||||
solver.Add(x[len1] > 0);
|
||||
solver.Add(x[len1+len2] > 0);
|
||||
|
||||
// symmetry breaking
|
||||
solver.Add(num1 < num2);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(all,
|
||||
Solver.INT_VAR_SIMPLE,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("{0} * {1} = {2}", num1.Value(), num2.Value(), res.Value());
|
||||
}
|
||||
|
||||
/*
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
*/
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
int bbase = 10;
|
||||
int start = 1;
|
||||
|
||||
if(args.Length > 0) {
|
||||
bbase = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if(args.Length > 1) {
|
||||
start = Convert.ToInt32(args[1]);
|
||||
}
|
||||
|
||||
int x_len = bbase - 1 + 1-start;
|
||||
for(int len1 = 0; len1 <= x_len; len1++) {
|
||||
for(int len2 = 0; len2 <= x_len; len2++) {
|
||||
if (x_len > len1 + len2
|
||||
&& len1 > 0 && len2 > 0
|
||||
) {
|
||||
Solve(bbase, start, len1, len2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
130
examples/dotnet/csharp/partition.cs
Normal file
130
examples/dotnet/csharp/partition.cs
Normal file
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Partition
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* This is a port of Charles Prud'homme's Java model
|
||||
* Partition.java
|
||||
* """
|
||||
* Partition n numbers into two groups, so that
|
||||
* - the sum of the first group equals the sum of the second,
|
||||
* - and the sum of the squares of the first group equals the sum of
|
||||
* the squares of the second
|
||||
* """
|
||||
*
|
||||
*/
|
||||
private static void Solve(int m)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Partition");
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(m, 1, 2 * m, "x");
|
||||
IntVar[] y = solver.MakeIntVarArray(m, 1, 2 * m, "y");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
// break symmetries
|
||||
for (int i = 0; i < m - 1; i++) {
|
||||
solver.Add(x[i] < x[i + 1]);
|
||||
solver.Add(y[i] < y[i + 1]);
|
||||
}
|
||||
solver.Add(x[0] < y[0]);
|
||||
|
||||
IntVar[] xy = new IntVar[2 * m];
|
||||
for (int i = m - 1; i >= 0; i--) {
|
||||
xy[i] = x[i];
|
||||
xy[m + i] = y[i];
|
||||
}
|
||||
|
||||
solver.Add(xy.AllDifferent());
|
||||
|
||||
int[] coeffs = new int[2 * m];
|
||||
for (int i = m - 1; i >= 0; i--) {
|
||||
coeffs[i] = 1;
|
||||
coeffs[m + i] = -1;
|
||||
}
|
||||
solver.Add(xy.ScalProd(coeffs) == 0);
|
||||
|
||||
IntVar[] sxy, sx, sy;
|
||||
sxy = new IntVar[2 * m];
|
||||
sx = new IntVar[m];
|
||||
sy = new IntVar[m];
|
||||
for (int i = m - 1; i >= 0; i--) {
|
||||
sx[i] = x[i].Square().Var();
|
||||
sxy[i] = sx[i];
|
||||
sy[i] = y[i].Square().Var();
|
||||
sxy[m + i] = sy[i];
|
||||
}
|
||||
solver.Add(sxy.ScalProd(coeffs) == 0);
|
||||
|
||||
solver.Add(x.Sum() == 2 * m * (2 * m + 1) / 4);
|
||||
solver.Add(y.Sum() == 2 * m * (2 * m + 1) / 4);
|
||||
solver.Add(sx.Sum() == 2 * m * (2 * m + 1) * (4 * m + 1) / 12);
|
||||
solver.Add(sy.Sum() == 2 * m * (2 * m + 1) * (4 * m + 1) / 12);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakeDefaultPhase(xy);
|
||||
|
||||
SearchMonitor log = solver.MakeSearchLog(10000);
|
||||
solver.NewSearch(db, log);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < m; i++) {
|
||||
Console.Write("[" + xy[i].Value() + "] ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
for(int i = 0; i < m; i++) {
|
||||
Console.Write("[" + xy[m+i].Value() + "] ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
}
|
||||
|
||||
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 m = 32;
|
||||
if (args.Length > 0) {
|
||||
m = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(m);
|
||||
}
|
||||
}
|
||||
144
examples/dotnet/csharp/perfect_square_sequence.cs
Normal file
144
examples/dotnet/csharp/perfect_square_sequence.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class PerfectSquareSequence
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Perfect square sequence.
|
||||
*
|
||||
* From 'Fun with num3ers'
|
||||
* "Sequence"
|
||||
* http://benvitale-funwithnum3ers.blogspot.com/2010/11/sequence.html
|
||||
* """
|
||||
* If we take the numbers from 1 to 15
|
||||
* (1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)
|
||||
* and rearrange them in such an order that any two consecutive
|
||||
* numbers in the sequence add up to a perfect square, we get,
|
||||
*
|
||||
* 8 1 15 10 6 3 13 12 4 5 11 14 2 7 9
|
||||
* 9 16 25 16 9 16 25 16 9 16 25 16 9 16
|
||||
*
|
||||
*
|
||||
* I ask the readers the following:
|
||||
*
|
||||
* Can you take the numbers from 1 to 25 to produce such an arrangement?
|
||||
* How about the numbers from 1 to 100?
|
||||
* """
|
||||
*
|
||||
* Via http://wildaboutmath.com/2010/11/26/wild-about-math-bloggers-111910
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/perfect_square_sequence.py
|
||||
*
|
||||
*/
|
||||
private static int Solve(int n = 15, int print_solutions=1, int show_num_sols=0)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("PerfectSquareSequence");
|
||||
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
// create the table of possible squares
|
||||
int[] squares = new int[n-1];
|
||||
for(int i = 1; i < n; i++) {
|
||||
squares[i-1] = i*i;
|
||||
}
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
for(int i = 1; i < n; i++) {
|
||||
solver.Add((x[i-1]+x[i]).Member(squares));
|
||||
}
|
||||
|
||||
// symmetry breaking
|
||||
solver.Add(x[0] < x[n-1]);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int num_solutions = 0;
|
||||
while (solver.NextSolution()) {
|
||||
num_solutions++;
|
||||
if (print_solutions > 0) {
|
||||
Console.Write("x: ");
|
||||
foreach(int i in RANGE) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
if (show_num_sols > 0 && num_solutions >= show_num_sols) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (print_solutions > 0) {
|
||||
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();
|
||||
|
||||
return num_solutions;
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
int n = 15;
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
for(int i = 2; i < 100; i++) {
|
||||
int num_solutions = Solve(i, 0, 0);
|
||||
Console.WriteLine("{0}: {1} solution(s)", i, num_solutions);
|
||||
}
|
||||
|
||||
} else {
|
||||
int num_solutions = Solve(n);
|
||||
Console.WriteLine("{0}: {1} solution(s)", n, num_solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
178
examples/dotnet/csharp/photo_problem.cs
Normal file
178
examples/dotnet/csharp/photo_problem.cs
Normal file
@@ -0,0 +1,178 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class PhotoProblem
|
||||
{
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Photo problem.
|
||||
*
|
||||
* Problem statement from Mozart/Oz tutorial:
|
||||
* http://www.mozart-oz.org/home/doc/fdt/node37.html#section.reified.photo
|
||||
* """
|
||||
* Betty, Chris, Donald, Fred, Gary, Mary, and Paul want to align in one
|
||||
* row for taking a photo. Some of them have preferences next to whom
|
||||
* they want to stand:
|
||||
*
|
||||
* 1. Betty wants to stand next to Gary and Mary.
|
||||
* 2. Chris wants to stand next to Betty and Gary.
|
||||
* 3. Fred wants to stand next to Mary and Donald.
|
||||
* 4. Paul wants to stand next to Fred and Donald.
|
||||
*
|
||||
* Obviously, it is impossible to satisfy all preferences. Can you find
|
||||
* an alignment that maximizes the number of satisfied preferences?
|
||||
* """
|
||||
*
|
||||
* Oz solution:
|
||||
* 6 # alignment(betty:5 chris:6 donald:1 fred:3 gary:7 mary:4 paul:2)
|
||||
* [5, 6, 1, 3, 7, 4, 2]
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/photo_problem.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int show_all_max=0)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("PhotoProblem");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
String[] persons = {"Betty", "Chris", "Donald", "Fred", "Gary", "Mary", "Paul"};
|
||||
int n = persons.Length;
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
int[,] preferences = {
|
||||
// 0 1 2 3 4 5 6
|
||||
// B C D F G M P
|
||||
{ 0,0,0,0,1,1,0 }, // Betty 0
|
||||
{ 1,0,0,0,1,0,0 }, // Chris 1
|
||||
{ 0,0,0,0,0,0,0 }, // Donald 2
|
||||
{ 0,0,1,0,0,1,0 }, // Fred 3
|
||||
{ 0,0,0,0,0,0,0 }, // Gary 4
|
||||
{ 0,0,0,0,0,0,0 }, // Mary 5
|
||||
{ 0,0,1,1,0,0,0 } // Paul 6
|
||||
};
|
||||
|
||||
Console.WriteLine("Preferences:");
|
||||
Console.WriteLine("1. Betty wants to stand next to Gary and Mary.");
|
||||
Console.WriteLine("2. Chris wants to stand next to Betty and Gary.");
|
||||
Console.WriteLine("3. Fred wants to stand next to Mary and Donald.");
|
||||
Console.WriteLine("4. Paul wants to stand next to Fred and Donald.\n");
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] positions = solver.MakeIntVarArray(n, 0, n-1, "positions");
|
||||
// successful preferences (to Maximize)
|
||||
IntVar z = solver.MakeIntVar(0, n*n, "z");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(positions.AllDifferent());
|
||||
|
||||
// calculate all the successful preferences
|
||||
solver.Add( ( from i in RANGE
|
||||
from j in RANGE
|
||||
where preferences[i,j] == 1
|
||||
select (positions[i] - positions[j]).Abs() == 1
|
||||
).ToArray().Sum() == z);
|
||||
|
||||
//
|
||||
// Symmetry breaking (from the Oz page):
|
||||
// Fred is somewhere left of Betty
|
||||
solver.Add(positions[3] < positions[0]);
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = z.Maximize(1);
|
||||
|
||||
if (show_all_max > 0) {
|
||||
Console.WriteLine("Showing all maximum solutions (z == 6).\n");
|
||||
solver.Add(z == 6);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(positions,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MAX_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("z: {0}", z.Value());
|
||||
int[] p = new int[n];
|
||||
Console.Write("p: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
p[i] = (int)positions[i].Value();
|
||||
Console.Write(p[i] + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (p[j] == i) {
|
||||
Console.Write(persons[j] + " ");
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Successful preferences:");
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (preferences[i,j] == 1 &&
|
||||
Math.Abs(p[i]-p[j])==1) {
|
||||
Console.WriteLine("\t{0} {1}", persons[i], persons[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nSolutions: " + solver.Solutions());
|
||||
Console.WriteLine("WallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
int show_all_max = 0;
|
||||
if (args.Length > 0) {
|
||||
show_all_max = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(show_all_max);
|
||||
}
|
||||
}
|
||||
141
examples/dotnet/csharp/place_number_puzzle.cs
Normal file
141
examples/dotnet/csharp/place_number_puzzle.cs
Normal file
@@ -0,0 +1,141 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class PlaceNumberPuzzle
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Place number puzzle.
|
||||
*
|
||||
* From
|
||||
* http://ai.uwaterloo.ca/~vanbeek/Courses/Slides/introduction.pdf
|
||||
* """
|
||||
* Place numbers 1 through 8 on nodes
|
||||
* - each number appears exactly once
|
||||
* - no connected nodes have consecutive numbers
|
||||
* 2 - 5
|
||||
* / | X | \
|
||||
* 1 - 3 - 6 - 8
|
||||
* \ | X | /
|
||||
* 4 - 7
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/place_number_puzzle.py
|
||||
*
|
||||
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("PlaceNumberPuzzle");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int m = 32;
|
||||
int n = 8;
|
||||
|
||||
// Note: this is 1-based for compatibility (and lazyness)
|
||||
int[,] graph = {
|
||||
{1,2},
|
||||
{1,3},
|
||||
{1,4},
|
||||
{2,1},
|
||||
{2,3},
|
||||
{2,5},
|
||||
{2,6},
|
||||
{3,2},
|
||||
{3,4},
|
||||
{3,6},
|
||||
{3,7},
|
||||
{4,1},
|
||||
{4,3},
|
||||
{4,6},
|
||||
{4,7},
|
||||
{5,2},
|
||||
{5,3},
|
||||
{5,6},
|
||||
{5,8},
|
||||
{6,2},
|
||||
{6,3},
|
||||
{6,4},
|
||||
{6,5},
|
||||
{6,7},
|
||||
{6,8},
|
||||
{7,3},
|
||||
{7,4},
|
||||
{7,6},
|
||||
{7,8},
|
||||
{8,5},
|
||||
{8,6},
|
||||
{8,7}
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
for(int i = 0; i < m; i++) {
|
||||
// (also base 0-base)
|
||||
solver.Add( (x[graph[i,0]-1]-x[graph[i,1]-1]).Abs() > 1);
|
||||
}
|
||||
|
||||
// symmetry breaking
|
||||
solver.Add(x[0] < x[n-1]);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
148
examples/dotnet/csharp/post_office_problem2.cs
Normal file
148
examples/dotnet/csharp/post_office_problem2.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// 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.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class PostOfficeProblem2
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Post office problem.
|
||||
*
|
||||
* Problem statement:
|
||||
* http://www-128.ibm.com/developerworks/linux/library/l-glpk2/
|
||||
*
|
||||
* From Winston 'Operations Research: Applications and Algorithms':
|
||||
* """
|
||||
* A post office requires a different number of full-time employees working
|
||||
* on different days of the week [summarized below]. Union rules state that
|
||||
* each full-time employee must work for 5 consecutive days and then receive
|
||||
* two days off. For example, an employee who works on Monday to Friday
|
||||
* must be off on Saturday and Sunday. The post office wants to meet its
|
||||
* daily requirements using only full-time employees. Minimize the number
|
||||
* of employees that must be hired.
|
||||
*
|
||||
* To summarize the important information about the problem:
|
||||
*
|
||||
* Every full-time worker works for 5 consecutive days and takes 2 days off
|
||||
* - Day 1 (Monday): 17 workers needed
|
||||
* - Day 2 : 13 workers needed
|
||||
* - Day 3 : 15 workers needed
|
||||
* - Day 4 : 19 workers needed
|
||||
* - Day 5 : 14 workers needed
|
||||
* - Day 6 : 16 workers needed
|
||||
* - Day 7 (Sunday) : 11 workers needed
|
||||
*
|
||||
* The post office needs to minimize the number of employees it needs
|
||||
* to hire to meet its demand.
|
||||
* """
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/post_office_problem2.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("PostOfficeProblem2");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
|
||||
// days 0..6, monday 0
|
||||
int n = 7;
|
||||
int[] need = {17, 13, 15, 19, 14, 16, 11};
|
||||
|
||||
// Total cost for the 5 day schedule.
|
||||
// Base cost per day is 100.
|
||||
// Working saturday is 100 extra
|
||||
// Working sunday is 200 extra.
|
||||
int[] cost = {500, 600, 800, 800, 800, 800, 700};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
|
||||
// No. of workers starting at day i
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, 100, "x");
|
||||
|
||||
IntVar total_cost = x.ScalProd(cost).Var();
|
||||
IntVar num_workers = x.Sum().Var();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < n; i++) {
|
||||
IntVar s = (from j in Enumerable.Range(0, n)
|
||||
where j != (i+5) % n && j != (i+6) % n
|
||||
select x[j]).ToArray().Sum().Var();
|
||||
solver.Add(s >= need[i]);
|
||||
}
|
||||
|
||||
// Add a limit for the cost
|
||||
solver.Add(total_cost <= 20000);
|
||||
|
||||
//
|
||||
|
||||
// objective
|
||||
//
|
||||
//
|
||||
OptimizeVar obj = total_cost.Minimize(100);
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("num_workers: {0}", num_workers.Value());
|
||||
Console.WriteLine("total_cost: {0}", total_cost.Value());
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine("\n");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
229
examples/dotnet/csharp/quasigroup_completion.cs
Normal file
229
examples/dotnet/csharp/quasigroup_completion.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class QuasigroupCompletion
|
||||
{
|
||||
|
||||
static int X = 0;
|
||||
|
||||
/*
|
||||
* default problem
|
||||
*
|
||||
* Example from Ruben Martins and Inès Lynce
|
||||
* Breaking Local Symmetries in Quasigroup Completion Problems, page 3
|
||||
* The solution is unique:
|
||||
*
|
||||
* 1 3 2 5 4
|
||||
* 2 5 4 1 3
|
||||
* 4 1 3 2 5
|
||||
* 5 4 1 3 2
|
||||
* 3 2 5 4 1
|
||||
*/
|
||||
static int default_n = 5;
|
||||
static int[,] default_problem = {{1, X, X, X, 4},
|
||||
{X, 5, X, X, X},
|
||||
{4, X, X, 2, X},
|
||||
{X, 4, X, X, X},
|
||||
{X, X, 5, X, 1}};
|
||||
|
||||
|
||||
// for the actual problem
|
||||
static int n;
|
||||
static int[,] problem;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves the Quasigroup Completion problem.
|
||||
* See http://www.hakank.org/or-tools/quasigroup_completion.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("QuasigroupCompletion");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
Console.WriteLine("Problem:");
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
Console.Write(problem[i,j] + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 1, n, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (problem[i,j] > X) {
|
||||
solver.Add(x[i,j] == problem[i,j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// rows and columns must be different
|
||||
//
|
||||
|
||||
// rows
|
||||
for(int i = 0; i < n; i++) {
|
||||
IntVar[] row = new IntVar[n];
|
||||
for(int j = 0; j < n; j++) {
|
||||
row[j] = x[i,j];
|
||||
}
|
||||
solver.Add(row.AllDifferent());
|
||||
}
|
||||
|
||||
// columns
|
||||
for(int j = 0; j < n; j++) {
|
||||
IntVar[] col = new IntVar[n];
|
||||
for(int i = 0; i < n; i++) {
|
||||
col[i] = x[i,j];
|
||||
}
|
||||
solver.Add(col.AllDifferent());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.INT_VAR_SIMPLE,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
int sol = 0;
|
||||
while (solver.NextSolution()) {
|
||||
sol++;
|
||||
Console.WriteLine("Solution #{0} ", sol + " ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++){
|
||||
Console.Write("{0} ", x[i,j].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Reads a Quasigroup completion file.
|
||||
* File format:
|
||||
* # a comment which is ignored
|
||||
* % a comment which also is ignored
|
||||
* number of rows (n)
|
||||
* <
|
||||
* row number of space separated entries
|
||||
* >
|
||||
*
|
||||
* "." or "0" means unknown, integer 1..n means known value
|
||||
*
|
||||
* Example
|
||||
* 5
|
||||
* 1 . . . 4
|
||||
* . 5 . . .
|
||||
* 4 . . 2 .
|
||||
* . 4 . . .
|
||||
* . . 5 . 1
|
||||
*
|
||||
*/
|
||||
private static void readFile(String file) {
|
||||
|
||||
Console.WriteLine("readFile(" + file + ")");
|
||||
int lineCount = 0;
|
||||
|
||||
TextReader inr = new StreamReader(file);
|
||||
String str;
|
||||
while ((str = inr.ReadLine()) != null && str.Length > 0) {
|
||||
|
||||
str = str.Trim();
|
||||
|
||||
// ignore comments
|
||||
if(str.StartsWith("#") || str.StartsWith("%")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Console.WriteLine(str);
|
||||
if (lineCount == 0) {
|
||||
n = Convert.ToInt32(str); // number of rows
|
||||
problem = new int[n,n];
|
||||
} else {
|
||||
// the problem matrix
|
||||
String[] row = Regex.Split(str, " ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
String s = row[i];
|
||||
if (s.Equals(".")) {
|
||||
problem[lineCount - 1, i] = 0;
|
||||
} else {
|
||||
problem[lineCount - 1, i] = Convert.ToInt32(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lineCount++;
|
||||
|
||||
} // end while
|
||||
|
||||
inr.Close();
|
||||
|
||||
|
||||
} // end readFile
|
||||
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
String file = "";
|
||||
if (args.Length > 0) {
|
||||
file = args[0];
|
||||
readFile(file);
|
||||
} else {
|
||||
problem = default_problem;
|
||||
n = default_n;
|
||||
}
|
||||
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
202
examples/dotnet/csharp/regex.cs
Normal file
202
examples/dotnet/csharp/regex.cs
Normal file
@@ -0,0 +1,202 @@
|
||||
//
|
||||
// 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.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class RegexGeneration
|
||||
{
|
||||
|
||||
/*
|
||||
* Global constraint regular
|
||||
*
|
||||
* This is a translation of MiniZinc's regular constraint (defined in
|
||||
* lib/zinc/globals.mzn), via the Comet code refered above.
|
||||
* All comments are from the MiniZinc code.
|
||||
* """
|
||||
* The sequence of values in array 'x' (which must all be in the range 1..S)
|
||||
* is accepted by the DFA of 'Q' states with input 1..S and transition
|
||||
* function 'd' (which maps (1..Q, 1..S) -> 0..Q)) and initial state 'q0'
|
||||
* (which must be in 1..Q) and accepting states 'F' (which all must be in
|
||||
* 1..Q). We reserve state 0 to be an always failing state.
|
||||
* """
|
||||
*
|
||||
* x : IntVar array
|
||||
* Q : number of states
|
||||
* S : input_max
|
||||
* d : transition matrix
|
||||
* q0: initial state
|
||||
* F : accepting states
|
||||
*
|
||||
*/
|
||||
static void MyRegular(Solver solver,
|
||||
IntVar[] x,
|
||||
int Q,
|
||||
int S,
|
||||
int[,] d,
|
||||
int q0,
|
||||
int[] F) {
|
||||
|
||||
|
||||
|
||||
// d2 is the same as d, except we add one extra transition for
|
||||
// each possible input; each extra transition is from state zero
|
||||
// to state zero. This allows us to continue even if we hit a
|
||||
// non-accepted input.
|
||||
int[][] d2 = new int[Q+1][];
|
||||
for(int i = 0; i <= Q; i++) {
|
||||
int[] row = new int[S];
|
||||
for(int j = 0; j < S; j++) {
|
||||
if (i == 0) {
|
||||
row[j] = 0;
|
||||
} else {
|
||||
row[j] = d[i-1,j];
|
||||
}
|
||||
}
|
||||
d2[i] = row;
|
||||
}
|
||||
|
||||
int[] d2_flatten = (from i in Enumerable.Range(0, Q+1)
|
||||
from j in Enumerable.Range(0, S)
|
||||
select d2[i][j]).ToArray();
|
||||
|
||||
// If x has index set m..n, then a[m-1] holds the initial state
|
||||
// (q0), and a[i+1] holds the state we're in after processing
|
||||
// x[i]. If a[n] is in F, then we succeed (ie. accept the
|
||||
// string).
|
||||
int m = 0;
|
||||
int n = x.Length;
|
||||
|
||||
IntVar[] a = solver.MakeIntVarArray(n+1-m, 0,Q+1, "a");
|
||||
// Check that the final state is in F
|
||||
solver.Add(a[a.Length-1].Member(F));
|
||||
// First state is q0
|
||||
solver.Add(a[m] == q0);
|
||||
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add(x[i] >= 1);
|
||||
solver.Add(x[i] <= S);
|
||||
// Determine a[i+1]: a[i+1] == d2[a[i], x[i]]
|
||||
solver.Add(a[i+1] == d2_flatten.Element(((a[i]*S)+(x[i]-1))));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Simple regular expression.
|
||||
*
|
||||
* My last name (Kjellerstrand) is quite often misspelled
|
||||
* in ways that this regular expression shows:
|
||||
* k(je|ä)ll(er|ar)?(st|b)r?an?d
|
||||
*
|
||||
* This model generates all the words that can be construed
|
||||
* by this regular expression.
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/regex.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n, List<String> res)
|
||||
{
|
||||
Solver solver = new Solver("RegexGeneration");
|
||||
|
||||
Console.WriteLine("\nn: {0}", n);
|
||||
|
||||
// The DFS (for regular)
|
||||
int n_states = 11;
|
||||
int input_max = 12;
|
||||
int initial_state = 1; // 0 is for the failing state
|
||||
int[] accepting_states = {12};
|
||||
|
||||
// The DFA
|
||||
int [,] transition_fn = {
|
||||
// 1 2 3 4 5 6 7 8 9 0 1 2 //
|
||||
{0,2,3,0,0,0,0,0,0,0,0,0}, // 1 k
|
||||
{0,0,0,4,0,0,0,0,0,0,0,0}, // 2 je
|
||||
{0,0,0,4,0,0,0,0,0,0,0,0}, // 3 ä
|
||||
{0,0,0,0,5,6,7,8,0,0,0,0}, // 4 ll
|
||||
{0,0,0,0,0,0,7,8,0,0,0,0}, // 5 er
|
||||
{0,0,0,0,0,0,7,8,0,0,0,0}, // 6 ar
|
||||
{0,0,0,0,0,0,0,0,9,10,0,0}, // 7 st
|
||||
{0,0,0,0,0,0,0,0,9,10,0,0}, // 8 b
|
||||
{0,0,0,0,0,0,0,0,0,10,0,0}, // 9 r
|
||||
{0,0,0,0,0,0,0,0,0,0,11,12}, // 10 a
|
||||
{0,0,0,0,0,0,0,0,0,0,0,12}, // 11 n
|
||||
// 12 d
|
||||
};
|
||||
|
||||
// Name of the states
|
||||
String[] s = {"k","je","ä","ll","er","ar","st","b","r","a","n","d"};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 1, input_max, "x");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
MyRegular(solver, x, n_states, input_max, transition_fn,
|
||||
initial_state, accepting_states);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
List<String> res2 = new List<String>();
|
||||
// State 1 (the start state) is not included in the
|
||||
// state array (x) so we add it first.
|
||||
res2.Add(s[0]);
|
||||
for(int i = 0; i < n; i++) {
|
||||
res2.Add(s[x[i].Value()-1]);
|
||||
}
|
||||
res.Add(String.Join("", res2.ToArray()));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
List<String> res = new List<String>();
|
||||
for(int n = 4; n <= 9; n++) {
|
||||
Solve(n, res);
|
||||
}
|
||||
Console.WriteLine("\nThe following {0} words where generated", res.Count);
|
||||
foreach(string r in res) {
|
||||
Console.WriteLine(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
356
examples/dotnet/csharp/rogo2.cs
Normal file
356
examples/dotnet/csharp/rogo2.cs
Normal file
@@ -0,0 +1,356 @@
|
||||
//
|
||||
// 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.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class Rogo2
|
||||
{
|
||||
|
||||
static int W = 0;
|
||||
static int B = -1;
|
||||
|
||||
// Default problem
|
||||
// Data from
|
||||
// Mike Trick: "Operations Research, Sudoko, Rogo, and Puzzles"
|
||||
// http://mat.tepper.cmu.edu/blog/?p=1302
|
||||
//
|
||||
// This has 48 solutions with symmetries;
|
||||
// 4 when the path symmetry is removed.
|
||||
//
|
||||
static int default_rows = 5;
|
||||
static int default_cols = 9;
|
||||
static int default_max_steps = 12;
|
||||
static int default_best = 8;
|
||||
static int[,] default_problem = {
|
||||
{2,W,W,W,W,W,W,W,W},
|
||||
{W,3,W,W,1,W,W,2,W},
|
||||
{W,W,W,W,W,W,B,W,2},
|
||||
{W,W,2,B,W,W,W,W,W},
|
||||
{W,W,W,W,2,W,W,1,W}
|
||||
};
|
||||
static String default_problem_name = "Problem Mike Trick";
|
||||
|
||||
|
||||
// The actual problem
|
||||
static int rows;
|
||||
static int cols;
|
||||
static int max_steps;
|
||||
static int best;
|
||||
static int[,] problem;
|
||||
static string problem_name;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Build the table of valid connections of the grid.
|
||||
*
|
||||
*/
|
||||
public static IntTupleSet ValidConnections(int rows, int cols)
|
||||
{
|
||||
|
||||
IEnumerable<int> ROWS = Enumerable.Range(0, rows);
|
||||
IEnumerable<int> COLS = Enumerable.Range(0, cols);
|
||||
var result_tmp = (
|
||||
from i1 in ROWS
|
||||
from j1 in COLS
|
||||
from i2 in ROWS
|
||||
from j2 in COLS
|
||||
where
|
||||
(Math.Abs(j1-j2) == 1 && i1 == i2) ||
|
||||
(Math.Abs(i1-i2) == 1 && j1 % cols == j2 % cols)
|
||||
select new int[] {i1*cols+j1, i2*cols+j2}
|
||||
).ToArray();
|
||||
|
||||
// Convert to len x 2 matrix
|
||||
int len = result_tmp.Length;
|
||||
IntTupleSet result = new IntTupleSet(2);
|
||||
foreach(int[] r in result_tmp) {
|
||||
result.Insert(r);
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Rogo puzzle solver.
|
||||
*
|
||||
* From http://www.rogopuzzle.co.nz/
|
||||
* """
|
||||
* The object is to collect the biggest score possible using a given
|
||||
* number of steps in a loop around a grid. The best possible score
|
||||
* for a puzzle is given with it, so you can easily check that you have
|
||||
* solved the puzzle. Rogo puzzles can also include forbidden squares,
|
||||
* which must be avoided in your loop.
|
||||
* """
|
||||
*
|
||||
* Also see Mike Trick:
|
||||
* "Operations Research, Sudoko, Rogo, and Puzzles"
|
||||
* http://mat.tepper.cmu.edu/blog/?p=1302
|
||||
*
|
||||
*
|
||||
* Also see, http://www.hakank.org/or-tools/rogo2.py
|
||||
* though this model differs in a couple of central points
|
||||
* which makes it much faster:
|
||||
*
|
||||
* - it use a table (
|
||||
AllowedAssignments) with the valid connections
|
||||
* - instead of two coordinates arrays, it use a single path array
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("Rogo2");
|
||||
|
||||
|
||||
Console.WriteLine("\n");
|
||||
Console.WriteLine("**********************************************");
|
||||
Console.WriteLine(" {0}", problem_name);
|
||||
Console.WriteLine("**********************************************\n");
|
||||
|
||||
//
|
||||
// Data
|
||||
//
|
||||
int B = -1;
|
||||
|
||||
Console.WriteLine("Rows: {0} Cols: {1} Max Steps: {2}", rows, cols, max_steps);
|
||||
|
||||
int[] problem_flatten = problem.Cast<int>().ToArray();
|
||||
int max_point = problem_flatten.Max();
|
||||
int max_sum = problem_flatten.Sum();
|
||||
Console.WriteLine("max_point: {0} max_sum: {1} best: {2}", max_point, max_sum, best);
|
||||
|
||||
IEnumerable<int> STEPS = Enumerable.Range(0, max_steps);
|
||||
IEnumerable<int> STEPS1 = Enumerable.Range(0, max_steps-1);
|
||||
|
||||
// the valid connections, to be used with AllowedAssignments
|
||||
IntTupleSet valid_connections = ValidConnections(rows, cols);
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] path = solver.MakeIntVarArray(max_steps, 0, rows*cols-1, "path");
|
||||
IntVar[] points = solver.MakeIntVarArray(max_steps, 0, best, "points");
|
||||
IntVar sum_points = points.Sum().VarWithName("sum_points");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
foreach(int s in STEPS) {
|
||||
// calculate the points (to maximize)
|
||||
solver.Add(points[s] == problem_flatten.Element(path[s]));
|
||||
|
||||
// ensure that there are no black cells in
|
||||
// the path
|
||||
solver.Add(problem_flatten.Element(path[s]) != B);
|
||||
}
|
||||
|
||||
solver.Add(path.AllDifferent());
|
||||
|
||||
|
||||
// valid connections
|
||||
foreach(int s in STEPS1) {
|
||||
solver.Add(new IntVar[] {path[s], path[s+1]}.
|
||||
AllowedAssignments(valid_connections));
|
||||
}
|
||||
// around the corner
|
||||
solver.Add(new IntVar[] {path[max_steps-1], path[0]}.
|
||||
AllowedAssignments(valid_connections));
|
||||
|
||||
|
||||
// Symmetry breaking
|
||||
for(int s = 1; s < max_steps; s++) {
|
||||
solver.Add(path[0] < path[s]);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Objective
|
||||
//
|
||||
OptimizeVar obj = sum_points.Maximize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(path,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("sum_points: {0}", sum_points.Value());
|
||||
Console.Write("path: ");
|
||||
foreach(int s in STEPS) {
|
||||
Console.Write("{0} ", path[s].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("(Adding 1 to coords...)");
|
||||
int[,] sol = new int[rows, cols];
|
||||
foreach(int s in STEPS) {
|
||||
int p = (int) path[s].Value();
|
||||
int x = (int) (p / cols);
|
||||
int y = (int) (p % cols);
|
||||
Console.WriteLine("{0,2},{1,2} ({2} points)", x+1, y+1, points[s].Value());
|
||||
sol[x, y] = 1;
|
||||
}
|
||||
Console.WriteLine("\nThe path is marked by 'X's:");
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
String p = sol[i,j] == 1 ? "X" : " ";
|
||||
String q = problem[i,j] == B ? "B" :
|
||||
problem[i,j] == 0 ? "." : problem[i,j].ToString();
|
||||
Console.Write("{0,2}{1} ", q, p);
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Reads a Rogo problem instance file.
|
||||
*
|
||||
* File format:
|
||||
* # a comment which is ignored
|
||||
* % a comment which also is ignored
|
||||
* rows
|
||||
* cols
|
||||
* max_step
|
||||
* best
|
||||
* <data>
|
||||
*
|
||||
* Where <data> is a rows x cols matrix of
|
||||
* digits (points), W (white), B (black)
|
||||
*
|
||||
* """
|
||||
* # comment
|
||||
* % another comment
|
||||
* 5
|
||||
* 9
|
||||
* 12
|
||||
* 8
|
||||
* 2 W W W W W W W W
|
||||
* W 3 W W 1 W W 2 W
|
||||
* W W W W W W B W 2
|
||||
* W W 2 B W W W W W
|
||||
* W W W W 2 W W 1 W
|
||||
* """
|
||||
*
|
||||
*/
|
||||
|
||||
private static void ReadFile(String file) {
|
||||
|
||||
Console.WriteLine("readFile(" + file + ")");
|
||||
|
||||
TextReader inr = new StreamReader(file);
|
||||
String str;
|
||||
int lineCount = 0;
|
||||
while ((str = inr.ReadLine()) != null && str.Length > 0) {
|
||||
str = str.Trim();
|
||||
|
||||
Console.WriteLine(str);
|
||||
|
||||
// ignore comments
|
||||
if(str.StartsWith("#") || str.StartsWith("%")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lineCount == 0) {
|
||||
rows = Convert.ToInt32(str);
|
||||
|
||||
} else if (lineCount == 1) {
|
||||
cols = Convert.ToInt32(str);
|
||||
problem = new int[rows, cols];
|
||||
|
||||
} else if (lineCount == 2) {
|
||||
max_steps = Convert.ToInt32(str);
|
||||
|
||||
} else if (lineCount == 3) {
|
||||
best = Convert.ToInt32(str);
|
||||
|
||||
} else {
|
||||
|
||||
String[] tmp = Regex.Split(str, "[,\\s]+");
|
||||
for(int j = 0; j < cols; j++) {
|
||||
int val = 0;
|
||||
if (tmp[j] == "B") {
|
||||
val = B;
|
||||
} else if (tmp[j] == "W") {
|
||||
val = W;
|
||||
} else {
|
||||
val = Convert.ToInt32(tmp[j]);
|
||||
}
|
||||
problem[lineCount-4, j] = val;
|
||||
}
|
||||
}
|
||||
|
||||
lineCount++;
|
||||
|
||||
} // end while
|
||||
|
||||
inr.Close();
|
||||
|
||||
} // end readFile
|
||||
|
||||
|
||||
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
|
||||
rows = default_rows;
|
||||
cols = default_cols;
|
||||
max_steps = default_max_steps;
|
||||
best = default_best;
|
||||
problem = default_problem;
|
||||
problem_name = default_problem_name;
|
||||
|
||||
String file = "";
|
||||
|
||||
if (args.Length > 0) {
|
||||
file = args[0];
|
||||
problem_name = "Problem " + file;
|
||||
ReadFile(file);
|
||||
}
|
||||
|
||||
Solve();
|
||||
|
||||
}
|
||||
}
|
||||
99
examples/dotnet/csharp/scheduling_speakers.cs
Normal file
99
examples/dotnet/csharp/scheduling_speakers.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// 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 SchedulingSpeakers
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Scheduling speakers problem
|
||||
*
|
||||
* From Rina Dechter, Constraint Processing, page 72
|
||||
* Scheduling of 6 speakers in 6 slots.
|
||||
*
|
||||
* See http://www.hakank.org/google_or_tools/scheduling_speakers.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("SchedulingSpeakers");
|
||||
|
||||
|
||||
// number of speakers
|
||||
int n = 6;
|
||||
|
||||
// slots available to speak
|
||||
int[][] available = {
|
||||
// Reasoning:
|
||||
new int[] {3,4,5,6}, // 2) the only one with 6 after speaker F -> 1
|
||||
new int[] {3,4}, // 5) 3 or 4
|
||||
new int[] {2,3,4,5}, // 3) only with 5 after F -> 1 and A -> 6
|
||||
new int[] {2,3,4}, // 4) only with 2 after C -> 5 and F -> 1
|
||||
new int[] {3,4}, // 5) 3 or 4
|
||||
new int[] {1,2,3,4,5,6} // 1) the only with 1
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 1, n, "x");
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
for(int i = 0; i < n; i++) {
|
||||
solver.Add(x[i].Member(available[i]));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine(string.Join(",", (from i in x select i.Value())));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
129
examples/dotnet/csharp/secret_santa.cs
Normal file
129
examples/dotnet/csharp/secret_santa.cs
Normal file
@@ -0,0 +1,129 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class SecretSanta
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Secret Santa problem in Google CP Solver.
|
||||
*
|
||||
* From Ruby Quiz Secret Santa
|
||||
* http://www.rubyquiz.com/quiz2.html
|
||||
* """
|
||||
* Honoring a long standing tradition started by my wife's dad, my friends
|
||||
* all play a Secret Santa game around Christmas time. We draw names and
|
||||
* spend a week sneaking that person gifts and clues to our identity. On the
|
||||
* last night of the game, we get together, have dinner, share stories, and,
|
||||
* most importantly, try to guess who our Secret Santa was. It's a crazily
|
||||
* fun way to enjoy each other's company during the holidays.
|
||||
*
|
||||
* To choose Santas, we use to draw names out of a hat. This system was
|
||||
* tedious, prone to many 'Wait, I got myself...' problems. This year, we
|
||||
* made a change to the rules that further complicated picking and we knew
|
||||
* the hat draw would not stand up to the challenge. Naturally, to solve
|
||||
* this problem, I scripted the process. Since that turned out to be more
|
||||
* interesting than I had expected, I decided to share.
|
||||
*
|
||||
* This weeks Ruby Quiz is to implement a Secret Santa selection script.
|
||||
* * Your script will be fed a list of names on STDIN.
|
||||
* ...
|
||||
* Your script should then choose a Secret Santa for every name in the list.
|
||||
* Obviously, a person cannot be their own Secret Santa. In addition, my friends
|
||||
* no longer allow people in the same family to be Santas for each other and your
|
||||
* script should take this into account.
|
||||
* """
|
||||
*
|
||||
* Comment: This model skips the file input and mail parts. We
|
||||
* assume that the friends are identified with a number from 1..n,
|
||||
* and the families is identified with a number 1..num_families.
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/secret_santa.py
|
||||
* Also see http://www.hakank.org/or-tools/secret_santa2.cs
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("SecretSanta");
|
||||
|
||||
int[] family = {1,1,1,1, 2, 3,3,3,3,3, 4,4};
|
||||
int n = family.Length;
|
||||
|
||||
Console.WriteLine("n = {0}", n);
|
||||
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, n-1, "x");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
// Can't be one own"s Secret Santa
|
||||
// (i.e. ensure that there are no fix-point in the array.)
|
||||
foreach(int i in RANGE) {
|
||||
solver.Add(x[i] != i);
|
||||
}
|
||||
|
||||
|
||||
// No Secret Santa to a person in the same family
|
||||
foreach(int i in RANGE) {
|
||||
solver.Add(solver.MakeIntConst(family[i]) != family.Element(x[i]));
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_SIMPLE,
|
||||
Solver.INT_VALUE_SIMPLE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.Write("x: ");
|
||||
foreach(int i in RANGE) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
248
examples/dotnet/csharp/secret_santa2.cs
Normal file
248
examples/dotnet/csharp/secret_santa2.cs
Normal file
@@ -0,0 +1,248 @@
|
||||
//
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class SecretSanta2
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Secret Santa problem II in Google CP Solver.
|
||||
*
|
||||
* From Maple Primes: 'Secret Santa Graph Theory'
|
||||
* http://www.mapleprimes.com/blog/jpmay/secretsantagraphtheory
|
||||
* """
|
||||
* Every year my extended family does a 'secret santa' gift exchange.
|
||||
* Each person draws another person at random and then gets a gift for
|
||||
* them. At first, none of my siblings were married, and so the draw was
|
||||
* completely random. Then, as people got married, we added the restriction
|
||||
* that spouses should not draw each others names. This restriction meant
|
||||
* that we moved from using slips of paper on a hat to using a simple
|
||||
* computer program to choose names. Then people began to complain when
|
||||
* they would get the same person two years in a row, so the program was
|
||||
* modified to keep some history and avoid giving anyone a name in their
|
||||
* recent history. This year, not everyone was participating, and so after
|
||||
* removing names, and limiting the number of exclusions to four per person,
|
||||
* I had data something like this:
|
||||
*
|
||||
* Name: Spouse, Recent Picks
|
||||
*
|
||||
* Noah: Ava. Ella, Evan, Ryan, John
|
||||
* Ava: Noah, Evan, Mia, John, Ryan
|
||||
* Ryan: Mia, Ella, Ava, Lily, Evan
|
||||
* Mia: Ryan, Ava, Ella, Lily, Evan
|
||||
* Ella: John, Lily, Evan, Mia, Ava
|
||||
* John: Ella, Noah, Lily, Ryan, Ava
|
||||
* Lily: Evan, John, Mia, Ava, Ella
|
||||
* Evan: Lily, Mia, John, Ryan, Noah
|
||||
* """
|
||||
*
|
||||
* Note: I interpret this as the following three constraints:
|
||||
* 1) One cannot be a Secret Santa of one's spouse
|
||||
* 2) One cannot be a Secret Santa for somebody two years in a row
|
||||
* 3) Optimization: maximize the time since the last time
|
||||
*
|
||||
* This model also handle single persons, something the original
|
||||
* problem don't mention.
|
||||
*
|
||||
*
|
||||
* Also see http://www.hakank.org/or-tools/secret_santa2.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int single=0)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("SecretSanta2");
|
||||
|
||||
Console.WriteLine("\nSingle: {0}", single);
|
||||
|
||||
//
|
||||
// The matrix version of earlier rounds.
|
||||
// M means that no earlier Santa has been assigned.
|
||||
// Note: Ryan and Mia has the same recipient for years 3 and 4,
|
||||
// and Ella and John has for year 4.
|
||||
// This seems to be caused by modification of
|
||||
// original data.
|
||||
//
|
||||
int n_no_single = 8;
|
||||
int M = n_no_single + 1;
|
||||
int[][] rounds_no_single = {
|
||||
// N A R M El J L Ev
|
||||
new int[] {0, M, 3, M, 1, 4, M, 2}, // Noah
|
||||
new int[] {M, 0, 4, 2, M, 3, M, 1}, // Ava
|
||||
new int[] {M, 2, 0, M, 1, M, 3, 4}, // Ryan
|
||||
new int[] {M, 1, M, 0, 2, M, 3, 4}, // Mia
|
||||
new int[] {M, 4, M, 3, 0, M, 1, 2}, // Ella
|
||||
new int[] {1, 4, 3, M, M, 0, 2, M}, // John
|
||||
new int[] {M, 3, M, 2, 4, 1, 0, M}, // Lily
|
||||
new int[] {4, M, 3, 1, M, 2, M, 0} // Evan
|
||||
};
|
||||
|
||||
//
|
||||
// Rounds with a single person (fake data)
|
||||
//
|
||||
int n_with_single = 9;
|
||||
M = n_with_single + 1;
|
||||
int[][] rounds_single = {
|
||||
// N A R M El J L Ev S
|
||||
new int[] {0, M, 3, M, 1, 4, M, 2, 2}, // Noah
|
||||
new int[] {M, 0, 4, 2, M, 3, M, 1, 1}, // Ava
|
||||
new int[] {M, 2, 0, M, 1, M, 3, 4, 4}, // Ryan
|
||||
new int[] {M, 1, M, 0, 2, M, 3, 4, 3}, // Mia
|
||||
new int[] {M, 4, M, 3, 0, M, 1, 2, M}, // Ella
|
||||
new int[] {1, 4, 3, M, M, 0, 2, M, M}, // John
|
||||
new int[] {M, 3, M, 2, 4, 1, 0, M, M}, // Lily
|
||||
new int[] {4, M, 3, 1, M, 2, M, 0, M}, // Evan
|
||||
new int[] {1, 2, 3, 4, M, 2, M, M, 0} // Single
|
||||
};
|
||||
|
||||
|
||||
int Noah = 0;
|
||||
int Ava = 1;
|
||||
int Ryan = 2;
|
||||
int Mia = 3;
|
||||
int Ella = 4;
|
||||
int John = 5;
|
||||
int Lily = 6;
|
||||
int Evan = 7;
|
||||
|
||||
int n = n_no_single;
|
||||
|
||||
int[][] rounds = rounds_no_single;
|
||||
if (single == 1) {
|
||||
n = n_with_single;
|
||||
rounds = rounds_single;
|
||||
}
|
||||
M = n + 1;
|
||||
|
||||
IEnumerable<int> RANGE = Enumerable.Range(0, n);
|
||||
|
||||
|
||||
|
||||
String[] persons = {"Noah", "Ava", "Ryan", "Mia", "Ella",
|
||||
"John", "Lily", "Evan", "Single"};
|
||||
|
||||
int[] spouses = {
|
||||
Ava, // Noah
|
||||
Noah, // Ava
|
||||
Mia, // Rya
|
||||
Ryan, // Mia
|
||||
John, // Ella
|
||||
Ella, // John
|
||||
Evan, // Lily
|
||||
Lily, // Evan
|
||||
-1 // Single has no spouse
|
||||
};
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] santas = solver.MakeIntVarArray(n, 0, n-1, "santas");
|
||||
IntVar[] santa_distance = solver.MakeIntVarArray(n, 0, M, "santa_distance");
|
||||
|
||||
// total of "distance", to maximize
|
||||
IntVar z = santa_distance.Sum().VarWithName("z");
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(santas.AllDifferent());
|
||||
|
||||
// Can't be one own"s Secret Santa
|
||||
// (i.e. ensure that there are no fix-point in the array.)
|
||||
foreach(int i in RANGE) {
|
||||
solver.Add(santas[i] != i);
|
||||
}
|
||||
|
||||
|
||||
// no Santa for a spouses
|
||||
foreach(int i in RANGE) {
|
||||
if (spouses[i] > -1) {
|
||||
solver.Add(santas[i] != spouses[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// optimize "distance" to earlier rounds:
|
||||
foreach(int i in RANGE) {
|
||||
solver.Add(santa_distance[i] == rounds[i].Element(santas[i]));
|
||||
}
|
||||
|
||||
|
||||
// cannot be a Secret Santa for the same person
|
||||
// two years in a row.
|
||||
foreach(int i in RANGE) {
|
||||
foreach(int j in RANGE) {
|
||||
if (rounds[i][j] == 1) {
|
||||
solver.Add(santas[i] != j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Objective (minimize the distances)
|
||||
//
|
||||
OptimizeVar obj = z.Maximize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(santas,
|
||||
Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
|
||||
Solver.ASSIGN_CENTER_VALUE);
|
||||
|
||||
solver.NewSearch(db, obj);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("\ntotal distances: {0}", z.Value());
|
||||
Console.Write("santas: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(santas[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
foreach(int i in RANGE) {
|
||||
Console.WriteLine("{0}\tis a Santa to {1} (distance {2})",
|
||||
persons[i],
|
||||
persons[santas[i].Value()],
|
||||
santa_distance[i].Value());
|
||||
}
|
||||
}
|
||||
|
||||
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 single = 0;
|
||||
Solve(single);
|
||||
single = 1;
|
||||
Solve(single);
|
||||
}
|
||||
}
|
||||
82
examples/dotnet/csharp/send_more_money.cs
Normal file
82
examples/dotnet/csharp/send_more_money.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class SendMoreMoney
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solve the SEND+MORE=MONEY problem
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("SendMoreMoney");
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar S = solver.MakeIntVar(0, 9, "S");
|
||||
IntVar E = solver.MakeIntVar(0, 9, "E");
|
||||
IntVar N = solver.MakeIntVar(0, 9, "N");
|
||||
IntVar D = solver.MakeIntVar(0, 9, "D");
|
||||
IntVar M = solver.MakeIntVar(0, 9, "M");
|
||||
IntVar O = solver.MakeIntVar(0, 9, "O");
|
||||
IntVar R = solver.MakeIntVar(0, 9, "R");
|
||||
IntVar Y = solver.MakeIntVar(0, 9, "Y");
|
||||
|
||||
// for AllDifferent()
|
||||
IntVar[] x = new IntVar[] {S,E,N,D,M,O,R,Y};
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
solver.Add(S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E ==
|
||||
M*10000 + O*1000 + N*100 + E*10 + Y);
|
||||
|
||||
solver.Add(S > 0);
|
||||
solver.Add(M > 0);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
Console.Write(x[i].ToString() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine("\nWallTime: " + solver.WallTime() + "ms ");
|
||||
Console.WriteLine("Failures: " + solver.Failures());
|
||||
Console.WriteLine("Branches: " + solver.Branches());
|
||||
|
||||
solver.EndSearch();
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
94
examples/dotnet/csharp/send_more_money2.cs
Normal file
94
examples/dotnet/csharp/send_more_money2.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class SendMoreMoney
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solve the SEND+MORE=MONEY problem
|
||||
* using scalar product.
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
Solver solver = new Solver("SendMoreMoney");
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar S = solver.MakeIntVar(0, 9, "S");
|
||||
IntVar E = solver.MakeIntVar(0, 9, "E");
|
||||
IntVar N = solver.MakeIntVar(0, 9, "N");
|
||||
IntVar D = solver.MakeIntVar(0, 9, "D");
|
||||
IntVar M = solver.MakeIntVar(0, 9, "M");
|
||||
IntVar O = solver.MakeIntVar(0, 9, "O");
|
||||
IntVar R = solver.MakeIntVar(0, 9, "R");
|
||||
IntVar Y = solver.MakeIntVar(0, 9, "Y");
|
||||
|
||||
// for AllDifferent()
|
||||
IntVar[] x = new IntVar[] {S,E,N,D,M,O,R,Y};
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
|
||||
/*
|
||||
solver.Add(S*1000 + E*100 + N*10 + D + M*1000 + O*100 + R*10 + E ==
|
||||
M*10000 + O*1000 + N*100 + E*10 + Y);
|
||||
*/
|
||||
|
||||
// Here we use scalar product instead.
|
||||
int[] s1 = new int[] {1000,100,10,1};
|
||||
int[] s2 = new int[] {10000,1000,100,10,1};
|
||||
solver.Add(new IntVar[] {S,E,N,D}.ScalProd(s1) +
|
||||
new IntVar[] {M,O,R,E}.ScalProd(s1) ==
|
||||
new IntVar[] {M,O,N,E,Y}.ScalProd(s2));
|
||||
|
||||
solver.Add(S > 0);
|
||||
solver.Add(M > 0);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
113
examples/dotnet/csharp/send_most_money.cs
Normal file
113
examples/dotnet/csharp/send_most_money.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class SendMostMoney
|
||||
{
|
||||
/**
|
||||
*
|
||||
* Solve the SEND+MOST=MONEY problem
|
||||
* where the object is to maximize MONEY
|
||||
* See http://www.hakank.org/google_or_tools/send_most_money.py
|
||||
*
|
||||
*/
|
||||
private static long Solve(long MONEY)
|
||||
{
|
||||
|
||||
Solver solver = new Solver("SendMostMoney");
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar S = solver.MakeIntVar(0, 9, "S");
|
||||
IntVar E = solver.MakeIntVar(0, 9, "E");
|
||||
IntVar N = solver.MakeIntVar(0, 9, "N");
|
||||
IntVar D = solver.MakeIntVar(0, 9, "D");
|
||||
IntVar M = solver.MakeIntVar(0, 9, "M");
|
||||
IntVar O = solver.MakeIntVar(0, 9, "O");
|
||||
IntVar T = solver.MakeIntVar(0, 9, "T");
|
||||
IntVar Y = solver.MakeIntVar(0, 9, "Y");
|
||||
|
||||
// for AllDifferent()
|
||||
IntVar[] x = new IntVar[] {S,E,N,D,M,O,T,Y};
|
||||
|
||||
IntVar[] eq = {S,E,N,D, M,O,S,T, M,O,N,E,Y};
|
||||
int[] coeffs = { 1000, 100, 10, 1, // S E N D +
|
||||
1000, 100, 10, 1, // M O S T
|
||||
-10000,-1000, -100,-10,-1 // == M O N E Y
|
||||
};
|
||||
solver.Add(eq.ScalProd(coeffs) == 0);
|
||||
|
||||
// IntVar money = solver.MakeScalProd(new IntVar[] {M, O, N, E, Y},
|
||||
// new int[] {10000, 1000, 100, 10, 1}).Var();
|
||||
IntVar money = (new IntVar[] {M, O, N, E, Y}).
|
||||
ScalProd(new int[] {10000, 1000, 100, 10, 1}).Var();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
solver.Add(x.AllDifferent());
|
||||
solver.Add(S > 0);
|
||||
solver.Add(M > 0);
|
||||
|
||||
if (MONEY > 0) {
|
||||
solver.Add(money == MONEY);
|
||||
}
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.CHOOSE_FIRST_UNBOUND,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
if (MONEY == 0) {
|
||||
OptimizeVar obj = money.Maximize(1);
|
||||
solver.NewSearch(db, obj);
|
||||
} else {
|
||||
solver.NewSearch(db);
|
||||
}
|
||||
|
||||
long money_ret = 0;
|
||||
while (solver.NextSolution()) {
|
||||
money_ret = money.Value();
|
||||
Console.WriteLine("money: {0}", money.Value() );
|
||||
for(int i = 0; i < x.Length; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
return money_ret;
|
||||
|
||||
}
|
||||
|
||||
public static void Main(String[] args)
|
||||
{
|
||||
Console.WriteLine("First get the max value of money:");
|
||||
long this_money = Solve(0);
|
||||
Console.WriteLine("\nThen we find all solutions for MONEY = {0}:", this_money);
|
||||
long tmp = Solve(this_money);
|
||||
}
|
||||
}
|
||||
122
examples/dotnet/csharp/seseman.cs
Normal file
122
examples/dotnet/csharp/seseman.cs
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// 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 Google.OrTools.ConstraintSolver;
|
||||
|
||||
|
||||
public class Seseman
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves the Seseman convent problem.
|
||||
* See http://www.hakank.org/google_or_tools/seseman.py
|
||||
*
|
||||
*/
|
||||
private static void Solve(int n = 3)
|
||||
{
|
||||
Solver solver = new Solver("Seseman");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
int border_sum = n * n;
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[,] x = solver.MakeIntVarMatrix(n, n, 0, n*n, "x");
|
||||
IntVar[] x_flat = x.Flatten();
|
||||
IntVar total_sum = x_flat.Sum().Var();
|
||||
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// zero in all middle cells
|
||||
for(int i = 1; i < n-1; i++) {
|
||||
for(int j = 1; j < n-1; j++) {
|
||||
solver.Add(x[i,j] == 0);
|
||||
}
|
||||
}
|
||||
|
||||
// all borders must be >= 1
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++) {
|
||||
if (i == 0 || j == 0 || i == n - 1 || j == n - 1) {
|
||||
solver.Add(x[i,j] >= 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// sum the four borders
|
||||
IntVar[] border1 = new IntVar[n];
|
||||
IntVar[] border2 = new IntVar[n];
|
||||
IntVar[] border3 = new IntVar[n];
|
||||
IntVar[] border4 = new IntVar[n];
|
||||
for(int i = 0; i < n; i++) {
|
||||
border1[i] = x[i,0];
|
||||
border2[i] = x[i,n-1];
|
||||
border3[i] = x[0,i];
|
||||
border4[i] = x[n-1,i];
|
||||
}
|
||||
solver.Add(border1.Sum() == border_sum);
|
||||
solver.Add(border2.Sum() == border_sum);
|
||||
solver.Add(border3.Sum() == border_sum);
|
||||
solver.Add(border4.Sum() == border_sum);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x_flat,
|
||||
Solver.CHOOSE_PATH,
|
||||
Solver.ASSIGN_MIN_VALUE);
|
||||
|
||||
solver.NewSearch(db);
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("total_sum: {0} ", total_sum.Value());
|
||||
for(int i = 0; i < n; i++) {
|
||||
for(int j = 0; j < n; j++){
|
||||
Console.Write("{0} ", x[i,j].Value());
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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 = 3;
|
||||
|
||||
if (args.Length > 0) {
|
||||
n = Convert.ToInt32(args[0]);
|
||||
}
|
||||
|
||||
Solve(n);
|
||||
}
|
||||
}
|
||||
109
examples/dotnet/csharp/set_covering.cs
Normal file
109
examples/dotnet/csharp/set_covering.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// 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 SetCovering
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves a set covering problem.
|
||||
* See See http://www.hakank.org/or-tools/set_covering.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("SetCovering");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
|
||||
// Placing of firestations, from Winston 'Operations Research',
|
||||
// page 486.
|
||||
int min_distance = 15;
|
||||
int num_cities = 6;
|
||||
|
||||
int[,] distance = {{ 0,10,20,30,30,20},
|
||||
{10, 0,25,35,20,10},
|
||||
{20,25, 0,15,30,20},
|
||||
{30,35,15, 0,15,25},
|
||||
{30,20,30,15, 0,14},
|
||||
{20,10,20,25,14, 0}};
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(num_cities, 0, 1, "x");
|
||||
IntVar z = x.Sum().Var();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// ensure that all cities are covered
|
||||
for(int i = 0; i < num_cities; i++) {
|
||||
IntVar[] b = (from j in Enumerable.Range(0, num_cities)
|
||||
where distance[i,j] <= min_distance
|
||||
select x[j]).ToArray();
|
||||
solver.Add(b.Sum() >= 1);
|
||||
|
||||
}
|
||||
|
||||
//
|
||||
// objective
|
||||
//
|
||||
OptimizeVar objective = z.Minimize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db, objective);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("z: {0}", z.Value());
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < num_cities; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
115
examples/dotnet/csharp/set_covering2.cs
Normal file
115
examples/dotnet/csharp/set_covering2.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class SetCovering2
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves a set covering problem.
|
||||
* See See http://www.hakank.org/or-tools/set_covering2.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("SetCovering2");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
|
||||
// Example 9.1-2 from
|
||||
// Taha "Operations Research - An Introduction",
|
||||
// page 354ff.
|
||||
// Minimize the number of security telephones in street
|
||||
// corners on a campus.
|
||||
|
||||
int n = 8; // maximum number of corners
|
||||
int num_streets = 11; // number of connected streets
|
||||
|
||||
// corners of each street
|
||||
// Note: 1-based (handled below)
|
||||
int[,] corner = {{1,2},
|
||||
{2,3},
|
||||
{4,5},
|
||||
{7,8},
|
||||
{6,7},
|
||||
{2,6},
|
||||
{1,6},
|
||||
{4,7},
|
||||
{2,4},
|
||||
{5,8},
|
||||
{3,5}};
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(n, 0, 1, "x");
|
||||
// number of telephones, to be minimized
|
||||
IntVar z = x.Sum().Var();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// ensure that all streets are covered
|
||||
for(int i = 0; i < num_streets; i++) {
|
||||
solver.Add(x[corner[i,0] - 1] + x[corner[i,1] - 1] >= 1);
|
||||
}
|
||||
|
||||
//
|
||||
// objective
|
||||
//
|
||||
OptimizeVar objective = z.Minimize(1);
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db, objective);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("z: {0}", z.Value());
|
||||
Console.Write("x: ");
|
||||
for(int i = 0; i < n; i++) {
|
||||
Console.Write(x[i].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
131
examples/dotnet/csharp/set_covering3.cs
Normal file
131
examples/dotnet/csharp/set_covering3.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
//
|
||||
// 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.Text.RegularExpressions;
|
||||
using Google.OrTools.ConstraintSolver;
|
||||
|
||||
public class SetCovering3
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
* Solves a set covering problem.
|
||||
* See See http://www.hakank.org/or-tools/set_covering3.py
|
||||
*
|
||||
*/
|
||||
private static void Solve()
|
||||
{
|
||||
|
||||
Solver solver = new Solver("SetCovering3");
|
||||
|
||||
//
|
||||
// data
|
||||
//
|
||||
|
||||
// Set covering problem from
|
||||
// Katta G. Murty: 'Optimization Models for Decision Making',
|
||||
// page 302f
|
||||
// http://ioe.engin.umich.edu/people/fac/books/murty/opti_model/junior-7.pdf
|
||||
int num_groups = 6;
|
||||
int num_senators = 10;
|
||||
|
||||
// which group does a senator belong to?
|
||||
int[,] belongs = {{1, 1, 1, 1, 1, 0, 0, 0, 0, 0}, // 1 southern
|
||||
{0, 0, 0, 0, 0, 1, 1, 1, 1, 1}, // 2 northern
|
||||
{0, 1, 1, 0, 0, 0, 0, 1, 1, 1}, // 3 liberals
|
||||
{1, 0, 0, 0, 1, 1, 1, 0, 0, 0}, // 4 conservative
|
||||
{0, 0, 1, 1, 1, 1, 1, 0, 1, 0}, // 5 democrats
|
||||
{1, 1, 0, 0, 0, 0, 0, 1, 0, 1}}; // 6 republicans
|
||||
|
||||
|
||||
//
|
||||
// Decision variables
|
||||
//
|
||||
IntVar[] x = solver.MakeIntVarArray(num_senators, 0, 1, "x");
|
||||
// number of assigned senators, to be minimized
|
||||
IntVar z = x.Sum().Var();
|
||||
|
||||
//
|
||||
// Constraints
|
||||
//
|
||||
|
||||
// ensure that each group is covered by at least
|
||||
// one senator
|
||||
for(int i = 0; i < num_groups; i++) {
|
||||
IntVar[] b = new IntVar[num_senators];
|
||||
for(int j = 0; j < num_senators; j++) {
|
||||
b[j] = (x[j]*belongs[i,j]).Var();
|
||||
}
|
||||
solver.Add(b.Sum() >= 1);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// objective
|
||||
//
|
||||
OptimizeVar objective = z.Minimize(1);
|
||||
|
||||
|
||||
//
|
||||
// Search
|
||||
//
|
||||
DecisionBuilder db = solver.MakePhase(x,
|
||||
Solver.INT_VAR_DEFAULT,
|
||||
Solver.INT_VALUE_DEFAULT);
|
||||
|
||||
solver.NewSearch(db, objective);
|
||||
|
||||
while (solver.NextSolution()) {
|
||||
Console.WriteLine("z: " + z.Value());
|
||||
Console.Write("x: ");
|
||||
for(int j = 0; j < num_senators; j++) {
|
||||
Console.Write(x[j].Value() + " ");
|
||||
}
|
||||
Console.WriteLine();
|
||||
|
||||
// More details
|
||||
for(int j = 0; j < num_senators; j++) {
|
||||
if (x[j].Value() == 1) {
|
||||
Console.Write("Senator " + (1 + j) +
|
||||
" belongs to these groups: ");
|
||||
for(int i = 0; i < num_groups; i++) {
|
||||
if (belongs[i,j] == 1) {
|
||||
Console.Write((1 + i) + " ");
|
||||
}
|
||||
}
|
||||
Console.WriteLine();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Solve();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user