Example #1
0
    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.ModelSat)
        {
            Console.WriteLine("x = " + solver.Value(x));
            Console.WriteLine("y = " + solver.Value(y));
            Console.WriteLine("z = " + solver.Value(z));
        }
    }
Example #2
0
        public void NegativeSquareVar()
        {
            CpModel model        = new CpModel();
            IntVar  boolvar      = model.NewBoolVar("boolvar");
            IntVar  x            = model.NewIntVar(0, 10, "x");
            IntVar  delta        = model.NewIntVar(-5, 5, "delta");
            IntVar  squaredDelta = model.NewIntVar(0, 25, "squaredDelta");

            model.Add(x == 4).OnlyEnforceIf(boolvar);
            model.Add(x == 0).OnlyEnforceIf(boolvar.Not());
            model.Add(delta == x - 5);
            long[,] tuples = { { -5, 25 }, { -4, 16 }, { -3, 9 }, { -2,  4 }, { -1,  1 }, { 0, 0 },
                               {  1,  1 }, {  2,  4 }, {  3, 9 }, {  4, 16 }, {  5, 25 } };
            model.AddAllowedAssignments(new IntVar[] { delta, squaredDelta }, tuples);
            model.Minimize(squaredDelta);

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

            CpSolverResponse response = solver.Response;

            Assert.Equal(1, solver.Value(boolvar));
            Assert.Equal(4, solver.Value(x));
            Assert.Equal(-1, solver.Value(delta));
            Assert.Equal(1, solver.Value(squaredDelta));
            Assert.Equal(new long[] { 1, 4, -1, 1 }, response.Solution);
            Assert.Equal(1.0, response.ObjectiveValue, 6);
        }
Example #3
0
    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.ModelSat)
        {
            Console.WriteLine("x = " + solver.Value(x));
            Console.WriteLine("y = " + solver.Value(y));
            Console.WriteLine("z = " + solver.Value(z));
        }
    }
Example #4
0
    static void TestNegativeSquareVar()
    {
        CpModel model = new CpModel();

        IntVar boolvar      = model.NewBoolVar("boolvar");
        IntVar x            = model.NewIntVar(0, 10, "x");
        IntVar delta        = model.NewIntVar(-5, 5, "delta");
        IntVar squaredDelta = model.NewIntVar(0, 25, "squaredDelta");

        model.Add(x == 4).OnlyEnforceIf(boolvar);
        model.Add(x == 0).OnlyEnforceIf(boolvar.Not());
        model.Add(delta == x - 5);

        long[,] tuples = { { -5, 25 }, { -4, 16 }, { -3, 9 }, { -2,  4 }, { -1,  1 }, { 0, 0 },
                           {  1,  1 }, {  2,  4 }, {  3, 9 }, {  4, 16 }, {  5, 25 } };
        model.AddAllowedAssignments(new IntVar[] { delta, squaredDelta }, tuples);

        model.Minimize(squaredDelta);

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

        Console.WriteLine(solver.ResponseStats());
    }
Example #5
0
        public void NegativeIntVar()
        {
            CpModel model        = new CpModel();
            IntVar  boolvar      = model.NewBoolVar("boolvar");
            IntVar  x            = model.NewIntVar(0, 10, "x");
            IntVar  delta        = model.NewIntVar(-5, 5, "delta");
            IntVar  squaredDelta = model.NewIntVar(0, 25, "squaredDelta");

            model.Add(x == boolvar * 4);
            model.Add(delta == x - 5);
            model.AddProdEquality(squaredDelta, new IntVar[] { delta, delta });
            model.Minimize(squaredDelta);
            // Console.WriteLine("model = " + model.Model.ToString());

            CpSolver         solver   = new CpSolver();
            CpSolverStatus   status   = solver.Solve(model);
            CpSolverResponse response = solver.Response;

            Console.WriteLine("response = " + response.ToString());

            Assert.Equal(CpSolverStatus.Optimal, status);

            Assert.Equal(1, solver.Value(boolvar));
            Assert.Equal(4, solver.Value(x));
            Assert.Equal(-1, solver.Value(delta));
            Assert.Equal(1, solver.Value(squaredDelta));
            Assert.Equal(new long[] { 1, 4, -1, 1 }, response.Solution);
            Assert.Equal(1.0, response.ObjectiveValue, 5);
        }
Example #6
0
        public void SimpleLinearModel()
        {
            CpModel model = new CpModel();
            IntVar  v1    = model.NewIntVar(-10, 10, "v1");
            IntVar  v2    = model.NewIntVar(-10, 10, "v2");
            IntVar  v3    = model.NewIntVar(-100000, 100000, "v3");

            model.AddLinearConstraint(v1 + v2, -1000000, 100000);
            model.AddLinearConstraint(v1 + 2 * v2 - v3, 0, 100000);
            model.Maximize(v3);
            Assert.Equal(v1.Domain.FlattenedIntervals(),
                         new long[] { -10, 10 });
            //Console.WriteLine("model = " + model.Model.ToString());

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

            Assert.Equal(CpSolverStatus.Optimal, status);

            CpSolverResponse response = solver.Response;

            Assert.Equal(30, response.ObjectiveValue);
            Assert.Equal(new long[] { 10, 10, 30 }, response.Solution);
            //Console.WriteLine("response = " + reponse.ToString());
        }
Example #7
0
    static void Main()
    {
        // Creates the model.
        // [START model]
        CpModel model = new CpModel();
        // [END model]

        // Creates the variables.
        // [START variables]
        int varUpperBound = new int[] { 50, 45, 37 }.Max();

        IntVar x = model.NewIntVar(0, varUpperBound, "x");
        IntVar y = model.NewIntVar(0, varUpperBound, "y");
        IntVar z = model.NewIntVar(0, varUpperBound, "z");

        // [END variables]

        // Creates the constraints.
        // [START constraints]
        model.Add(2 * x + 7 * y + 3 * z <= 50);
        model.Add(3 * x - 5 * y + 7 * z <= 45);
        model.Add(5 * x + 2 * y - 6 * z <= 37);
        // [END constraints]

        // [START objective]
        model.Maximize(2 * x + 2 * y + 3 * z);
        // [END objective]

        // Creates a solver and solves the model.
        // [START solve]
        CpSolver       solver = new CpSolver();
        CpSolverStatus status = solver.Solve(model);

        // [END solve]

        // [START print_solution]
        if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
        {
            Console.WriteLine($"Maximum of objective function: {solver.ObjectiveValue}");
            Console.WriteLine("x = " + solver.Value(x));
            Console.WriteLine("y = " + solver.Value(y));
            Console.WriteLine("z = " + solver.Value(z));
        }
        else
        {
            Console.WriteLine("No solution found.");
        }
        // [END print_solution]

        // [START statistics]
        Console.WriteLine("Statistics");
        Console.WriteLine($"  conflicts: {solver.NumConflicts()}");
        Console.WriteLine($"  branches : {solver.NumBranches()}");
        Console.WriteLine($"  wall time: {solver.WallTime()}s");
        // [END statistics]
    }
Example #8
0
    static void Main()
    {
        CpModel model = new CpModel();
        // Three weeks.
        int horizon = 21;

        // Task 0, duration 2.
        IntVar      start_0    = model.NewIntVar(0, horizon, "start_0");
        int         duration_0 = 2;
        IntVar      end_0      = model.NewIntVar(0, horizon, "end_0");
        IntervalVar task_0     =
            model.NewIntervalVar(start_0, duration_0, end_0, "task_0");

        //  Task 1, duration 4.
        IntVar      start_1    = model.NewIntVar(0, horizon, "start_1");
        int         duration_1 = 4;
        IntVar      end_1      = model.NewIntVar(0, horizon, "end_1");
        IntervalVar task_1     =
            model.NewIntervalVar(start_1, duration_1, end_1, "task_1");

        // Task 2, duration 3.
        IntVar      start_2    = model.NewIntVar(0, horizon, "start_2");
        int         duration_2 = 3;
        IntVar      end_2      = model.NewIntVar(0, horizon, "end_2");
        IntervalVar task_2     =
            model.NewIntervalVar(start_2, duration_2, end_2, "task_2");

        // Weekends.
        IntervalVar weekend_0 = model.NewIntervalVar(5, 2, 7, "weekend_0");
        IntervalVar weekend_1 = model.NewIntervalVar(12, 2, 14, "weekend_1");
        IntervalVar weekend_2 = model.NewIntervalVar(19, 2, 21, "weekend_2");

        // No Overlap constraint.
        model.AddNoOverlap(new IntervalVar[] { task_0, task_1, task_2, weekend_0,
                                               weekend_1, weekend_2 });

        // Makespan objective.
        IntVar obj = model.NewIntVar(0, horizon, "makespan");

        model.AddMaxEquality(obj, new IntVar[] { end_0, end_1, end_2 });
        model.Minimize(obj);

        // Creates a solver and solves the model.
        CpSolver       solver = new CpSolver();
        CpSolverStatus status = solver.Solve(model);

        if (status == CpSolverStatus.Optimal)
        {
            Console.WriteLine("Optimal Schedule Length: " + solver.ObjectiveValue);
            Console.WriteLine("Task 0 starts at " + solver.Value(start_0));
            Console.WriteLine("Task 1 starts at " + solver.Value(start_1));
            Console.WriteLine("Task 2 starts at " + solver.Value(start_2));
        }
    }
Example #9
0
    static void TestSimpleLinearModel2()
    {
        Console.WriteLine("TestSimpleLinearModel2");
        CpModel model = new CpModel();
        IntVar  v1    = model.NewIntVar(-10, 10, "v1");
        IntVar  v2    = model.NewIntVar(-10, 10, "v2");

        model.AddLinearConstraint(new[] { v1, v2 }, new[] { 1, 1 }, -1000000, 100000);
        model.Maximize(v1 - 2 * v2);

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

        Check(status == CpSolverStatus.Optimal, "Wrong status after solve");
        CheckDoubleEq(30.0, solver.ObjectiveValue, "Wrong solution value");
        Console.WriteLine("response = " + solver.Response.ToString());
    }
Example #10
0
        public void SimpleLinearModel2()
        {
            CpModel model = new CpModel();
            IntVar v1 = model.NewIntVar(-10, 10, "v1");
            IntVar v2 = model.NewIntVar(-10, 10, "v2");
            model.AddLinearConstraint(new[] {v1, v2}, new[] {1, 1}, -1000000, 100000);
            model.Maximize(v1 - 2 * v2);
            //Console.WriteLine("model = " + model.Model.ToString());

            CpSolver solver = new CpSolver();
            CpSolverStatus status = solver.Solve(model);
            Assert.Equal(CpSolverStatus.Optimal, status);

            CpSolverResponse response = solver.Response;
            Assert.Equal(30, response.ObjectiveValue);
            Assert.Equal(new long[] {10, -10}, response.Solution);
            //Console.WriteLine("response = " + reponse.ToString());
        }
Example #11
0
    static void TestDivision()
    {
        Console.WriteLine("TestDivision");
        CpModel model = new CpModel();
        IntVar  v1    = model.NewIntVar(0, 10, "v1");
        IntVar  v2    = model.NewIntVar(1, 10, "v2");

        model.AddDivisionEquality(3, v1, v2);

        Console.WriteLine(model.Model);

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

        Check(status == CpSolverStatus.Feasible, "Wrong status after solve");
        Console.WriteLine("v1 = {0}", solver.Value(v1));
        Console.WriteLine("v2 = {0}", solver.Value(v2));
    }
Example #12
0
        public void Modulo()
        {
            CpModel model = new CpModel();
            IntVar v1 = model.NewIntVar(1, 10, "v1");
            IntVar v2 = model.NewIntVar(1, 10, "v2");
            model.AddModuloEquality(3, v1, v2);
            //Console.WriteLine(model.Model);

            CpSolver solver = new CpSolver();
            CpSolverStatus status = solver.Solve(model);
            Assert.Equal(CpSolverStatus.Feasible, status);

            CpSolverResponse response = solver.Response;
            Assert.Equal(3, solver.Value(v1));
            Assert.Equal(4, solver.Value(v2));
            Assert.Equal(new long[] {3, 4, 3}, response.Solution);
            Assert.Equal(0, response.ObjectiveValue);
            //Console.WriteLine("response = " + reponse.ToString());
        }
Example #13
0
    static void TestSimpleLinearModel3()
    {
        Console.WriteLine("TestSimpleLinearModel3");
        CpModel model = new CpModel();
        IntVar  v1    = model.NewIntVar(-10, 10, "v1");
        IntVar  v2    = model.NewIntVar(-10, 10, "v2");

        model.Add(-100000 <= v1 + 2 * v2 <= 100000);
        model.Minimize(v1 - 2 * v2);

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

        Check(status == CpSolverStatus.Optimal, "Wrong status after solve");
        CheckDoubleEq(-30.0, solver.ObjectiveValue, "Wrong solution value");
        CheckLongEq(-10, solver.Value(v1), "Wrong value");
        CheckLongEq(10, solver.Value(v2), "Wrong value");
        CheckLongEq(-30, solver.Value(v1 - 2 * v2), "Wrong value");
    }
Example #14
0
        public void SolverTest(bool callGC)
        {
            CpModel model = new CpModel();

            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");

            model.Add(x != y);

            CpSolver solver = new CpSolver();

            if (callGC)
            {
                GC.Collect();
            }
            CpSolverStatus status = solver.Solve(model);
        }
Example #15
0
    static void Main()
    {
        // Creates the model.
        // [START model]
        CpModel model = new CpModel();
        // [END model]

        // Creates the variables.
        // [START 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");

        // [END variables]

        // Creates the constraints.
        // [START constraints]
        model.Add(x != y);
        // [END constraints]

        // Creates a solver and solves the model.
        // [START solve]
        CpSolver       solver = new CpSolver();
        CpSolverStatus status = solver.Solve(model);

        // [END solve]

        // [START print_solution]
        if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
        {
            Console.WriteLine("x = " + solver.Value(x));
            Console.WriteLine("y = " + solver.Value(y));
            Console.WriteLine("z = " + solver.Value(z));
        }
        else
        {
            Console.WriteLine("No solution found.");
        }
        // [END print_solution]
    }
Example #16
0
        public void SimpleLinearModel3()
        {
            CpModel model = new CpModel();
            IntVar v1 = model.NewIntVar(-10, 10, "v1");
            IntVar v2 = model.NewIntVar(-10, 10, "v2");
            model.Add(-100000 <= v1 + 2 * v2 <= 100000);
            model.Minimize(v1 - 2 * v2);
            //Console.WriteLine("model = " + model.Model.ToString());

            CpSolver solver = new CpSolver();
            CpSolverStatus status = solver.Solve(model);
            Assert.Equal(CpSolverStatus.Optimal, status);

            CpSolverResponse response = solver.Response;
            Assert.Equal(-10, solver.Value(v1));
            Assert.Equal(10, solver.Value(v2));
            Assert.Equal(new long[] {-10, 10}, response.Solution);
            Assert.Equal(-30, solver.Value(v1 - 2 * v2));
            Assert.Equal(-30, response.ObjectiveValue);
            //Console.WriteLine("response = " + reponse.ToString());
        }
Example #17
0
    static void TestSimpleLinearModel()
    {
        Console.WriteLine("TestSimpleLinearModel");
        CpModel model = new CpModel();
        IntVar  v1    = model.NewIntVar(-10, 10, "v1");
        IntVar  v2    = model.NewIntVar(-10, 10, "v2");
        IntVar  v3    = model.NewIntVar(-100000, 100000, "v3");

        model.AddLinearConstraint(new[] { v1, v2 }, new[] { 1, 1 }, -1000000, 100000);
        model.AddLinearConstraint(new[] { v1, v2, v3 }, new[] { 1, 2, -1 }, 0, 100000);

        model.Maximize(v3);

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

        Check(status == CpSolverStatus.Optimal, "Wrong status after solve");
        Console.WriteLine("Status = " + status);
        Console.WriteLine("model = " + model.Model.ToString());
        Console.WriteLine("response = " + solver.Response.ToString());
    }
Example #18
0
    static void Main()
    {
        // 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.Optimal)
        {
            Console.WriteLine(solver.Value(r) + " rabbits, and " + solver.Value(p) + " pheasants");
        }
    }
    static void Main()
    {
        // Creates the model.
        // [START model]
        CpModel model = new CpModel();
        // [END model]

        // Creates the variables.
        // [START 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");

        // [END variables]

        // Creates the constraints.
        // [START constraints]
        model.Add(x != y);
        // [END constraints]

        // Solution hinting: x <- 1, y <- 2
        model.AddHint(x, 1);
        model.AddHint(y, 2);

        // [START objective]
        model.Maximize(LinearExpr.ScalProd(new IntVar[] { x, y, z }, new int[] { 1, 2, 3 }));
        // [END objective]

        // Creates a solver and solves the model.
        // [START solve]
        CpSolver solver            = new CpSolver();
        VarArraySolutionPrinter cb =
            new VarArraySolutionPrinter(new IntVar[] { x, y, z });
        CpSolverStatus status = solver.SolveWithSolutionCallback(model, cb);
        // [END solve]
    }
Example #20
0
    static void TestNegativeIntVar()
    {
        CpModel model = new CpModel();

        IntVar boolvar      = model.NewBoolVar("boolvar");
        IntVar x            = model.NewIntVar(0, 10, "x");
        IntVar delta        = model.NewIntVar(-5, 5, "delta");
        IntVar squaredDelta = model.NewIntVar(0, 25, "squaredDelta");

        // model.Add(x == 4).OnlyEnforceIf(boolvar);
        // model.Add(x == 0).OnlyEnforceIf(boolvar.Not());
        model.Add(x == boolvar * 4);
        model.Add(delta == x - 5);

        model.AddProdEquality(squaredDelta, new IntVar[] { delta, delta });
        model.Minimize(squaredDelta);

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

        Console.WriteLine(solver.ResponseStats());
    }
Example #21
0
    static void Main()
    {
        // Creates the model.
        // [START model]
        CpModel model = new CpModel();
        // [END model]

        // Creates the variables.
        // [START variables]
        IntVar   x = model.NewIntVar(0, 10, "x");
        IntVar   y = model.NewIntVar(0, 10, "y");
        IntVar   z = model.NewIntVar(0, 10, "z");
        ILiteral a = model.NewBoolVar("a");
        ILiteral b = model.NewBoolVar("b");
        ILiteral c = model.NewBoolVar("c");

        // [END variables]

        // Creates the constraints.
        // [START constraints]
        model.Add(x > y).OnlyEnforceIf(a);
        model.Add(y > z).OnlyEnforceIf(b);
        model.Add(z > x).OnlyEnforceIf(c);
        // [END constraints]

        // Add assumptions
        model.AddAssumptions(new ILiteral[] { a, b, c });

        // Creates a solver and solves the model.
        // [START solve]
        CpSolver       solver = new CpSolver();
        CpSolverStatus status = solver.Solve(model);

        Console.WriteLine(solver.SufficientAssumptionsForInfeasibility());
        // [END solve]
    }
Example #22
0
    static void Main()
    {
        // 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(LinearExpr.Sum(tmp) == 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(LinearExpr.Sum(tmp) == 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.AddLinearConstraint(LinearExpr.Sum(tmp), 1, 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(LinearExpr.Sum(tmp) <= 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());
    }
Example #23
0
    public static void SolveInstance1(RPQ_Instance instance)
    {
        CpModel  model  = new CpModel();
        CpSolver solver = new CpSolver();
        //maksymalnawartosczmiennych,liczonazduzaprzesada
        int variablesMaxValue = 0;

        foreach (RPQ_Job job in instance.jobs)
        {
            variablesMaxValue += job.r + job.p + job.q;
        }

        var alfas = new IntVar[instance.jobs.Count, instance.jobs.Count];

        for (int i = 0; i < instance.jobs.Count; i++)
        {
            for (int j = 0; j < instance.jobs.Count; j++)
            {
                alfas[i, j] = model.NewIntVar(0, 1, "alfa" + i + "_" + j);
            }
        }
        var starts = new IntVar[instance.jobs.Count];

        for (int i = 0; i < instance.jobs.Count; i++)
        {
            starts[i] = model.NewIntVar(0, variablesMaxValue, "starts" + i);
        }
        //cmax:
        var cmax = model.NewIntVar(0, variablesMaxValue, "cmax");

        //ograniczenia:
        //kazdezzadanmusizostacnajpierwprzygotowane:
        foreach (RPQ_Job job in instance.jobs)
        {
            model.Add(starts[job.id] >= job.r);
        }
        //Cmaxmusibycmniejszyodwszystkichczasowzakonczen(zq):
        foreach (RPQ_Job job in instance.jobs)
        {
            model.Add(cmax >= starts[job.id] + job.p + job.q);
        }
        //ogariczeniaodpowiadajacezakolejnoscwykonywaniazadan:
        for (int i = 0; i < instance.jobs.Count; i++)
        {
            for (int j = i + 1; j < instance.jobs.Count; j++)
            {
                var job1 = instance.jobs[i];
                var job2 = instance.jobs[j];
                model.Add(starts[job1.id] + job1.p <= starts[job2.id] +
                          alfas[job1.id, job2.id] * variablesMaxValue);
                model.Add(starts[job2.id] + job2.p <= starts[job1.id] +
                          alfas[job2.id, job1.id] * variablesMaxValue);
                model.Add(alfas[job1.id, job2.id] + alfas[job2.id, job1.id] == 1);
            }
        }
        model.Minimize(cmax);
        CpSolverStatus resultStatus = solver.Solve(model);

        //Console.WriteLine(solver.ResponseStats());

        if (resultStatus != CpSolverStatus.Optimal)
        {
            Console.WriteLine("Solver didn’t find optimal solution!");
        }
        Console.WriteLine("Objective value=" + solver.ObjectiveValue);
    }
Example #24
0
    static void Main()
    {
        // Data.
        // [START data_model]
        int[,] costs =
        {
            {  90,  80, 75,  70 },
            {  35,  85, 55,  65 },
            { 125,  95, 90,  95 },
            {  45, 110, 95, 115 },
            {  50, 100, 90, 100 },
        };
        int[] costsFlat =
        {
            90, 80, 75, 70, 35, 85, 55, 65, 125, 95, 90, 95, 45, 110, 95, 115, 50, 100, 90, 100
        };
        int numWorkers = costs.GetLength(0);
        int numTasks   = costs.GetLength(1);
        // [END data_model]

        // Model.
        // [START model]
        CpModel model = new CpModel();

        // [END model]

        // Variables.
        // [START variables]
        IntVar[,] x = new IntVar[numWorkers, numTasks];
        // Variables in a 1-dim array.
        IntVar[] xFlat = new IntVar[numWorkers * numTasks];
        for (int i = 0; i < numWorkers; ++i)
        {
            for (int j = 0; j < numTasks; ++j)
            {
                x[i, j] = model.NewIntVar(0, 1, $"worker_{i}_task_{j}");
                int k = i * numTasks + j;
                xFlat[k] = x[i, j];
            }
        }
        // [END variables]

        // Constraints
        // [START constraints]
        // Each worker is assigned to at most one task.
        int[] onesTasks = { 1, 1, 1, 1 };
        for (int i = 0; i < numWorkers; ++i)
        {
            IntVar[] vars = new IntVar[numTasks];
            for (int j = 0; j < numTasks; ++j)
            {
                vars[j] = x[i, j];
            }
            model.Add(LinearExpr.ScalProd(vars, onesTasks) <= 1);
        }

        // Each task is assigned to exactly one worker.
        int[] onesWorkers = { 1, 1, 1, 1, 1 };
        for (int j = 0; j < numTasks; ++j)
        {
            IntVar[] vars = new IntVar[numWorkers];
            for (int i = 0; i < numWorkers; ++i)
            {
                vars[i] = x[i, j];
            }
            model.Add(LinearExpr.ScalProd(vars, onesWorkers) == 1);
        }
        // [END constraints]

        // Objective
        // [START objective]
        model.Minimize(LinearExpr.ScalProd(xFlat, costsFlat));
        // [END objective]

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

        Console.WriteLine($"Solve status: {status}");
        // [END solve]

        // Print solution.
        // [START print_solution]
        // Check that the problem has a feasible solution.
        if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
        {
            Console.WriteLine($"Total cost: {solver.ObjectiveValue}\n");
            for (int i = 0; i < numWorkers; ++i)
            {
                for (int j = 0; j < numTasks; ++j)
                {
                    if (solver.Value(x[i, j]) > 0.5)
                    {
                        Console.WriteLine($"Worker {i} assigned to task {j}. Cost: {costs[i, j]}");
                    }
                }
            }
        }
        else
        {
            Console.WriteLine("No solution found.");
        }
        // [END print_solution]

        Console.WriteLine("Statistics");
        Console.WriteLine($"  - conflicts : {solver.NumConflicts()}");
        Console.WriteLine($"  - branches  : {solver.NumBranches()}");
        Console.WriteLine($"  - wall time : {solver.WallTime()}s");
    }
Example #25
0
    public static void Main(String[] args)
    {
        // Instantiate the data problem.
        // [START data]
        int[] Weights  = { 48, 30, 42, 36, 36, 48, 42, 42, 36, 24, 30, 30, 42, 36, 36 };
        int[] Values   = { 10, 30, 25, 50, 35, 30, 15, 40, 30, 35, 45, 10, 20, 30, 25 };
        int   NumItems = Weights.Length;

        int[] allItems = Enumerable.Range(0, NumItems).ToArray();

        int[] BinCapacities = { 100, 100, 100, 100, 100 };
        int   NumBins       = BinCapacities.Length;

        int[] allBins = Enumerable.Range(0, NumBins).ToArray();
        // [END data]

        // Model.
        // [START model]
        CpModel model = new CpModel();

        // [END model]

        // Variables.
        // [START variables]
        ILiteral[,] x = new ILiteral[NumItems, NumBins];
        foreach (int i in allItems)
        {
            foreach (int b in allBins)
            {
                x[i, b] = model.NewBoolVar($"x_{i}_{b}");
            }
        }
        // [END variables]

        // Constraints.
        // [START constraints]
        // Each item is assigned to at most one bin.
        foreach (int i in allItems)
        {
            List <ILiteral> literals = new List <ILiteral>();
            foreach (int b in allBins)
            {
                literals.Add(x[i, b]);
            }
            model.AddAtMostOne(literals);
        }

        // The amount packed in each bin cannot exceed its capacity.
        foreach (int b in allBins)
        {
            List <ILiteral> items = new List <ILiteral>();
            foreach (int i in allItems)
            {
                items.Add(x[i, b]);
            }
            model.Add(LinearExpr.WeightedSum(items, Weights) <= BinCapacities[b]);
        }
        // [END constraints]

        // Objective.
        // [START objective]
        LinearExprBuilder obj = LinearExpr.NewBuilder();

        foreach (int i in allItems)
        {
            foreach (int b in allBins)
            {
                obj.AddTerm(x[i, b], Values[i]);
            }
        }
        model.Maximize(obj);
        //  [END objective]

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

        // [END solve]

        // Print solution.
        // [START print_solution]
        // Check that the problem has a feasible solution.
        if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
        {
            Console.WriteLine($"Total packed value: {solver.ObjectiveValue}");
            double TotalWeight = 0.0;
            foreach (int b in allBins)
            {
                double BinWeight = 0.0;
                double BinValue  = 0.0;
                Console.WriteLine($"Bin {b}");
                foreach (int i in allItems)
                {
                    if (solver.BooleanValue(x[i, b]))
                    {
                        Console.WriteLine($"Item {i} weight: {Weights[i]} values: {Values[i]}");
                        BinWeight += Weights[i];
                        BinValue  += Values[i];
                    }
                }
                Console.WriteLine("Packed bin weight: " + BinWeight);
                Console.WriteLine("Packed bin value: " + BinValue);
                TotalWeight += BinWeight;
            }
            Console.WriteLine("Total packed weight: " + TotalWeight);
        }
        else
        {
            Console.WriteLine("No solution found.");
        }
        // [END print_solution]

        // [START statistics]
        Console.WriteLine("Statistics");
        Console.WriteLine($"  conflicts: {solver.NumConflicts()}");
        Console.WriteLine($"  branches : {solver.NumBranches()}");
        Console.WriteLine($"  wall time: {solver.WallTime()}s");
        // [END statistics]
    }
Example #26
0
    public static void Main(String[] args)
    {
        // Data.
        // [START data_model]
        int[,] costs =
        {
            { 90, 80, 75, 70 }, { 35, 85, 55, 65 }, { 125, 95, 90, 95 }, { 45, 110, 95, 115 }, { 50, 100, 90, 100 },
        };
        int numWorkers = costs.GetLength(0);
        int numTasks   = costs.GetLength(1);
        // [END data_model]

        // Model.
        // [START model]
        CpModel model = new CpModel();

        // [END model]

        // Variables.
        // [START variables]
        BoolVar[,] x = new BoolVar[numWorkers, numTasks];
        // Variables in a 1-dim array.
        for (int worker = 0; worker < numWorkers; ++worker)
        {
            for (int task = 0; task < numTasks; ++task)
            {
                x[worker, task] = model.NewBoolVar($"worker_{worker}_task_{task}");
            }
        }
        // [END variables]

        // Constraints
        // [START constraints]
        // Each worker is assigned to at most one task.
        for (int worker = 0; worker < numWorkers; ++worker)
        {
            List <ILiteral> tasks = new List <ILiteral>();
            for (int task = 0; task < numTasks; ++task)
            {
                tasks.Add(x[worker, task]);
            }
            model.AddAtMostOne(tasks);
        }

        // Each task is assigned to exactly one worker.
        for (int task = 0; task < numTasks; ++task)
        {
            List <ILiteral> workers = new List <ILiteral>();
            for (int worker = 0; worker < numWorkers; ++worker)
            {
                workers.Add(x[worker, task]);
            }
            model.AddExactlyOne(workers);
        }
        // [END constraints]

        // Objective
        // [START objective]
        LinearExprBuilder obj = LinearExpr.NewBuilder();

        for (int worker = 0; worker < numWorkers; ++worker)
        {
            for (int task = 0; task < numTasks; ++task)
            {
                obj.AddTerm((IntVar)x[worker, task], costs[worker, task]);
            }
        }
        model.Minimize(obj);
        // [END objective]

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

        Console.WriteLine($"Solve status: {status}");
        // [END solve]

        // Print solution.
        // [START print_solution]
        // Check that the problem has a feasible solution.
        if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
        {
            Console.WriteLine($"Total cost: {solver.ObjectiveValue}\n");
            for (int i = 0; i < numWorkers; ++i)
            {
                for (int j = 0; j < numTasks; ++j)
                {
                    if (solver.Value(x[i, j]) > 0.5)
                    {
                        Console.WriteLine($"Worker {i} assigned to task {j}. Cost: {costs[i, j]}");
                    }
                }
            }
        }
        else
        {
            Console.WriteLine("No solution found.");
        }
        // [END print_solution]

        Console.WriteLine("Statistics");
        Console.WriteLine($"  - conflicts : {solver.NumConflicts()}");
        Console.WriteLine($"  - branches  : {solver.NumBranches()}");
        Console.WriteLine($"  - wall time : {solver.WallTime()}s");
    }
Example #27
0
    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()));
    }
Example #28
0
        public Sudoku Solve(Sudoku s)
        {
            CpModel model = new CpModel();

            IntVar[][] tab_s = new IntVar[9][];
            for (int i = 0; i < tab_s.Length; i++)
            {
                tab_s[i] = new IntVar[9];
            }

            for (int i = 0; i < tab_s.Length; i++)
            {
                for (int j = 0; j < tab_s[i].Length; j++)
                {
                    tab_s[i][j] = model.NewIntVar(1, 9, "grid" + "(" + i + "," + j + ")");
                }
            }

            //constraints all differents on rows
            for (int i = 0; i < tab_s.Length; i++)
            {
                model.AddAllDifferent(tab_s[i]);
            }
            // Constraints all differents on colums
            IntVar[] tpm = new IntVar[9];
            for (int j = 0; j < tab_s[0].Length; j++)
            {
                for (int i = 0; i < tab_s.Length; i++)
                {
                    tpm[i] = tab_s[i][j];
                }
                model.AddAllDifferent(tpm);
                Array.Clear(tpm, 0, tpm.Length);
            }

            // Constraint all differents on cells
            List <IntVar> ls = new List <IntVar>();

            for (int i = 0; i < 7; i += 3)
            {
                for (int j = 0; j < 7; j += 3)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        for (int l = 0; l < 3; l++)
                        {
                            ls.Add(tab_s[i + k][j + l]);
                        }
                    }
                    model.AddAllDifferent(ls);
                    ls.Clear();
                }
            }

            //initial Value
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 9; j++)
                {
                    if (s.GetCell(i, j) != 0)
                    {
                        model.Add(tab_s[i][j] == s.GetCell(i, j));
                    }
                }
            }

            //creation of the Solver
            CpSolver       solver = new CpSolver();
            CpSolverStatus status = solver.Solve(model);
            List <int>     lsol   = new List <int>();

            if (status == CpSolverStatus.Feasible)
            {
                for (int i = 0; i < 9; i++)
                {
                    for (int j = 0; j < 9; j++)
                    {
                        lsol.Add((int)(solver.Value(tab_s[i][j])));
                    }
                }
            }

            Sudoku resolu = new Sudoku(lsol);

            return(resolu);
        }
    static void Main()
    {
        CpModel model = new CpModel();
        // Three weeks.
        int horizon   = 100;
        int num_tasks = 4;

        IntVar[]      starts    = new IntVar[num_tasks];
        IntVar[]      ends      = new IntVar[num_tasks];
        IntervalVar[] intervals = new IntervalVar[num_tasks];
        ILiteral[]    presences = new ILiteral[num_tasks];
        IntVar[]      ranks     = new IntVar[num_tasks];

        IntVar true_var = model.NewConstant(1);

        // Creates intervals, half of them are optional.
        for (int t = 0; t < num_tasks; ++t)
        {
            starts[t] = model.NewIntVar(0, horizon, String.Format("start_{0}", t));
            int duration = t + 1;
            ends[t] = model.NewIntVar(0, horizon, String.Format("end_{0}", t));
            if (t < num_tasks / 2)
            {
                intervals[t] = model.NewIntervalVar(starts[t], duration, ends[t],
                                                    String.Format("interval_{0}", t));
                presences[t] = true_var;
            }
            else
            {
                presences[t] = model.NewBoolVar(String.Format("presence_{0}", t));
                intervals[t] = model.NewOptionalIntervalVar(
                    starts[t], duration, ends[t], presences[t],
                    String.Format("o_interval_{0}", t));
            }

            // Ranks = -1 if and only if the tasks is not performed.
            ranks[t] =
                model.NewIntVar(-1, num_tasks - 1, String.Format("rank_{0}", t));
        }

        // Adds NoOverlap constraint.
        model.AddNoOverlap(intervals);

        // Adds ranking constraint.
        RankTasks(model, starts, presences, ranks);

        // Adds a constraint on ranks.
        model.Add(ranks[0] < ranks[1]);

        // Creates makespan variable.
        IntVar makespan = model.NewIntVar(0, horizon, "makespan");

        for (int t = 0; t < num_tasks; ++t)
        {
            model.Add(ends[t] <= makespan).OnlyEnforceIf(presences[t]);
        }
        // Minimizes makespan - fixed gain per tasks performed.
        // As the fixed cost is less that the duration of the last interval,
        // the solver will not perform the last interval.
        IntVar[] presences_as_int_vars = new IntVar[num_tasks];
        for (int t = 0; t < num_tasks; ++t)
        {
            presences_as_int_vars[t] = (IntVar)presences[t];
        }
        model.Minimize(2 * makespan - 7 * presences_as_int_vars.Sum());

        // Creates a solver and solves the model.
        CpSolver       solver = new CpSolver();
        CpSolverStatus status = solver.Solve(model);

        if (status == CpSolverStatus.Optimal)
        {
            Console.WriteLine(String.Format("Optimal cost: {0}",
                                            solver.ObjectiveValue));
            Console.WriteLine(String.Format("Makespan: {0}", solver.Value(makespan)));
            for (int t = 0; t < num_tasks; ++t)
            {
                if (solver.BooleanValue(presences[t]))
                {
                    Console.WriteLine(String.Format(
                                          "Task {0} starts at {1} with rank {2}",
                                          t, solver.Value(starts[t]), solver.Value(ranks[t])));
                }
                else
                {
                    Console.WriteLine(String.Format(
                                          "Task {0} in not performed and ranked at {1}", t,
                                          solver.Value(ranks[t])));
                }
            }
        }
        else
        {
            Console.WriteLine(
                String.Format("Solver exited with nonoptimal status: {0}", status));
        }
    }
Example #30
0
    // [END assigned_task]

    public static void Main(String[] args)
    {
        // [START data]
        var allJobs =
            new[] {
            new[] {
                // job0
                new { machine = 0, duration = 3 },     // task0
                new { machine = 1, duration = 2 },     // task1
                new { machine = 2, duration = 2 },     // task2
            }
            .ToList(),
            new[] {
                // job1
                new { machine = 0, duration = 2 },     // task0
                new { machine = 2, duration = 1 },     // task1
                new { machine = 1, duration = 4 },     // task2
            }
            .ToList(),
            new[] {
                // job2
                new { machine = 1, duration = 4 },     // task0
                new { machine = 2, duration = 3 },     // task1
            }
            .ToList(),
        }
        .ToList();

        int numMachines = 0;

        foreach (var job in allJobs)
        {
            foreach (var task in job)
            {
                numMachines = Math.Max(numMachines, 1 + task.machine);
            }
        }
        int[] allMachines = Enumerable.Range(0, numMachines).ToArray();

        // Computes horizon dynamically as the sum of all durations.
        int horizon = 0;

        foreach (var job in allJobs)
        {
            foreach (var task in job)
            {
                horizon += task.duration;
            }
        }
        // [END data]

        // Creates the model.
        // [START model]
        CpModel model = new CpModel();
        // [END model]

        // [START variables]
        Dictionary <Tuple <int, int>, Tuple <IntVar, IntVar, IntervalVar> > allTasks =
            new Dictionary <Tuple <int, int>, Tuple <IntVar, IntVar, IntervalVar> >(); // (start, end, duration)
        Dictionary <int, List <IntervalVar> > machineToIntervals = new Dictionary <int, List <IntervalVar> >();

        for (int jobID = 0; jobID < allJobs.Count(); ++jobID)
        {
            var job = allJobs[jobID];
            for (int taskID = 0; taskID < job.Count(); ++taskID)
            {
                var         task     = job[taskID];
                String      suffix   = $"_{jobID}_{taskID}";
                IntVar      start    = model.NewIntVar(0, horizon, "start" + suffix);
                IntVar      end      = model.NewIntVar(0, horizon, "end" + suffix);
                IntervalVar interval = model.NewIntervalVar(start, task.duration, end, "interval" + suffix);
                var         key      = Tuple.Create(jobID, taskID);
                allTasks[key] = Tuple.Create(start, end, interval);
                if (!machineToIntervals.ContainsKey(task.machine))
                {
                    machineToIntervals.Add(task.machine, new List <IntervalVar>());
                }
                machineToIntervals[task.machine].Add(interval);
            }
        }
        // [END variables]

        // [START constraints]
        // Create and add disjunctive constraints.
        foreach (int machine in allMachines)
        {
            model.AddNoOverlap(machineToIntervals[machine]);
        }

        // Precedences inside a job.
        for (int jobID = 0; jobID < allJobs.Count(); ++jobID)
        {
            var job = allJobs[jobID];
            for (int taskID = 0; taskID < job.Count() - 1; ++taskID)
            {
                var key     = Tuple.Create(jobID, taskID);
                var nextKey = Tuple.Create(jobID, taskID + 1);
                model.Add(allTasks[nextKey].Item1 >= allTasks[key].Item2);
            }
        }
        // [END constraints]

        // [START objective]
        // Makespan objective.
        IntVar objVar = model.NewIntVar(0, horizon, "makespan");

        List <IntVar> ends = new List <IntVar>();

        for (int jobID = 0; jobID < allJobs.Count(); ++jobID)
        {
            var job = allJobs[jobID];
            var key = Tuple.Create(jobID, job.Count() - 1);
            ends.Add(allTasks[key].Item2);
        }
        model.AddMaxEquality(objVar, ends);
        model.Minimize(objVar);
        // [END objective]

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

        Console.WriteLine($"Solve status: {status}");
        // [END solve]

        // [START print_solution]
        if (status == CpSolverStatus.Optimal || status == CpSolverStatus.Feasible)
        {
            Console.WriteLine("Solution:");

            Dictionary <int, List <AssignedTask> > assignedJobs = new Dictionary <int, List <AssignedTask> >();
            for (int jobID = 0; jobID < allJobs.Count(); ++jobID)
            {
                var job = allJobs[jobID];
                for (int taskID = 0; taskID < job.Count(); ++taskID)
                {
                    var task  = job[taskID];
                    var key   = Tuple.Create(jobID, taskID);
                    int start = (int)solver.Value(allTasks[key].Item1);
                    if (!assignedJobs.ContainsKey(task.machine))
                    {
                        assignedJobs.Add(task.machine, new List <AssignedTask>());
                    }
                    assignedJobs[task.machine].Add(new AssignedTask(jobID, taskID, start, task.duration));
                }
            }

            // Create per machine output lines.
            String output = "";
            foreach (int machine in allMachines)
            {
                // Sort by starting time.
                assignedJobs[machine].Sort();
                String solLineTasks = $"Machine {machine}: ";
                String solLine      = "           ";

                foreach (var assignedTask in assignedJobs[machine])
                {
                    String name = $"job_{assignedTask.jobID}_task_{assignedTask.taskID}";
                    // Add spaces to output to align columns.
                    solLineTasks += $"{name,-15}";

                    String solTmp = $"[{assignedTask.start},{assignedTask.start+assignedTask.duration}]";
                    // Add spaces to output to align columns.
                    solLine += $"{solTmp,-15}";
                }
                output += solLineTasks + "\n";
                output += solLine + "\n";
            }
            // Finally print the solution found.
            Console.WriteLine($"Optimal Schedule Length: {solver.ObjectiveValue}");
            Console.WriteLine($"\n{output}");
        }
        else
        {
            Console.WriteLine("No solution found.");
        }
        // [END print_solution]

        // [START statistics]
        Console.WriteLine("Statistics");
        Console.WriteLine($"  conflicts: {solver.NumConflicts()}");
        Console.WriteLine($"  branches : {solver.NumBranches()}");
        Console.WriteLine($"  wall time: {solver.WallTime()}s");
        // [END statistics]
    }