Example #1
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 #2
0
    // [END solution_printer]

    static void Main()
    {
        // Constraint programming engine
        // [START model]
        CpModel model = new CpModel();
        // [START model]

        // [START variables]
        int BoardSize = 8;

        IntVar[] queens = new IntVar[BoardSize];
        for (int i = 0; i < BoardSize; ++i)
        {
            queens[i] = model.NewIntVar(0, BoardSize - 1, $"x{i}");
        }
        // [END variables]

        // Define constraints.
        // [START constraints]
        // All rows must be different.
        model.AddAllDifferent(queens);

        // All columns must be different because the indices of queens are all different.
        // No two queens can be on the same diagonal.
        LinearExpr[] diag1 = new LinearExpr[BoardSize];
        LinearExpr[] diag2 = new LinearExpr[BoardSize];
        for (int i = 0; i < BoardSize; ++i)
        {
            diag1[i] = LinearExpr.Affine(queens[i], /*coeff=*/ 1, /*offset=*/ i);
            diag2[i] = LinearExpr.Affine(queens[i], /*coeff=*/ 1, /*offset=*/ -i);
        }

        model.AddAllDifferent(diag1);
        model.AddAllDifferent(diag2);
        // [END constraints]

        // [START solve]
        // Creates a solver and solves the model.
        CpSolver        solver = new CpSolver();
        SolutionPrinter cb     = new SolutionPrinter(queens);

        // Search for all solutions.
        solver.StringParameters = "enumerate_all_solutions:true";
        // And solve.
        solver.Solve(model, cb);
        // [END solve]

        // [START statistics]
        Console.WriteLine("Statistics");
        Console.WriteLine($"  conflicts : {solver.NumConflicts()}");
        Console.WriteLine($"  branches  : {solver.NumBranches()}");
        Console.WriteLine($"  wall time : {solver.WallTime()} s");
        Console.WriteLine($"  number of solutions found: {cb.SolutionCount()}");
        // [END statistics]
    }
Example #3
0
    // [END solution_printer]

    // Solve the CP+IS+FUN==TRUE cryptarithm.
    static void Main()
    {
        // Constraint programming engine
        // [START model]
        CpModel model = new CpModel();
        // [START model]

        // [START variables]
        int kBase = 10;

        IntVar c = model.NewIntVar(1, kBase - 1, "C");
        IntVar p = model.NewIntVar(0, kBase - 1, "P");
        IntVar i = model.NewIntVar(1, kBase - 1, "I");
        IntVar s = model.NewIntVar(0, kBase - 1, "S");
        IntVar f = model.NewIntVar(1, kBase - 1, "F");
        IntVar u = model.NewIntVar(0, kBase - 1, "U");
        IntVar n = model.NewIntVar(0, kBase - 1, "N");
        IntVar t = model.NewIntVar(1, kBase - 1, "T");
        IntVar r = model.NewIntVar(0, kBase - 1, "R");
        IntVar e = model.NewIntVar(0, kBase - 1, "E");

        // We need to group variables in a list to use the constraint AllDifferent.
        IntVar[] letters = new IntVar[] { c, p, i, s, f, u, n, t, r, e };
        // [END variables]

        // [START constraints]
        // Define constraints.
        model.AddAllDifferent(letters);

        // CP + IS + FUN = TRUE
        model.Add(c * kBase + p + i * kBase + s + f * kBase * kBase + u * kBase + n ==
                  t * kBase * kBase * kBase + r * kBase * kBase + u * kBase + e);
        // [END constraints]

        // [START solve]
        // Creates a solver and solves the model.
        CpSolver solver            = new CpSolver();
        VarArraySolutionPrinter cb = new VarArraySolutionPrinter(letters);

        // Search for all solutions.
        solver.StringParameters = "enumerate_all_solutions:true";
        // And solve.
        solver.Solve(model, cb);
        // [END solve]

        // [START statistics]
        Console.WriteLine("Statistics");
        Console.WriteLine($"  conflicts : {solver.NumConflicts()}");
        Console.WriteLine($"  branches  : {solver.NumBranches()}");
        Console.WriteLine($"  wall time : {solver.WallTime()} s");
        Console.WriteLine($"  number of solutions found: {cb.SolutionCount()}");
        // [END statistics]
    }
Example #4
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 #5
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 #6
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 #7
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 #8
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 #9
0
    static void Main()
    {
        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.NewIntVar(0, horizon, String.Format("start_{0}_on_m0", i));
            IntVar      end0      = model.NewIntVar(0, horizon, 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.NewIntVar(0, horizon, String.Format("start_{0}_on_m1", i));
            IntVar      end1      = model.NewIntVar(0, horizon, 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");
    }
Example #10
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]
    }
Example #11
0
    public static void Main(String[] args)
    {
        // [START data]
        const int numNurses = 5;
        const int numDays   = 7;
        const int numShifts = 3;

        int[] allNurses = Enumerable.Range(0, numNurses).ToArray();
        int[] allDays   = Enumerable.Range(0, numDays).ToArray();
        int[] allShifts = Enumerable.Range(0, numShifts).ToArray();

        int[,,] shiftRequests = new int[, , ] {
            {
                { 0, 0, 1 },
                { 0, 0, 0 },
                { 0, 0, 0 },
                { 0, 0, 0 },
                { 0, 0, 1 },
                { 0, 1, 0 },
                { 0, 0, 1 },
            },
            {
                { 0, 0, 0 },
                { 0, 0, 0 },
                { 0, 1, 0 },
                { 0, 1, 0 },
                { 1, 0, 0 },
                { 0, 0, 0 },
                { 0, 0, 1 },
            },
            {
                { 0, 1, 0 },
                { 0, 1, 0 },
                { 0, 0, 0 },
                { 1, 0, 0 },
                { 0, 0, 0 },
                { 0, 1, 0 },
                { 0, 0, 0 },
            },
            {
                { 0, 0, 1 },
                { 0, 0, 0 },
                { 1, 0, 0 },
                { 0, 1, 0 },
                { 0, 0, 0 },
                { 1, 0, 0 },
                { 0, 0, 0 },
            },
            {
                { 0, 0, 0 },
                { 0, 0, 1 },
                { 0, 1, 0 },
                { 0, 0, 0 },
                { 1, 0, 0 },
                { 0, 1, 0 },
                { 0, 0, 0 },
            },
        };
        // [END data]

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

        // Creates shift variables.
        // shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
        // [START variables]
        Dictionary <Tuple <int, int, int>, IntVar> shifts = new Dictionary <Tuple <int, int, int>, IntVar>();

        foreach (int n in allNurses)
        {
            foreach (int d in allDays)
            {
                foreach (int s in allShifts)
                {
                    shifts.Add(Tuple.Create(n, d, s), model.NewBoolVar($"shifts_n{n}d{d}s{s}"));
                }
            }
        }
        // [END variables]

        // Each shift is assigned to exactly one nurse in the schedule period.
        // [START exactly_one_nurse]
        foreach (int d in allDays)
        {
            foreach (int s in allShifts)
            {
                IntVar[] x = new IntVar[numNurses];
                foreach (int n in allNurses)
                {
                    var key = Tuple.Create(n, d, s);
                    x[n] = shifts[key];
                }
                model.Add(LinearExpr.Sum(x) == 1);
            }
        }
        // [END exactly_one_nurse]

        // Each nurse works at most one shift per day.
        // [START at_most_one_shift]
        foreach (int n in allNurses)
        {
            foreach (int d in allDays)
            {
                IntVar[] x = new IntVar[numShifts];
                foreach (int s in allShifts)
                {
                    var key = Tuple.Create(n, d, s);
                    x[s] = shifts[key];
                }
                model.Add(LinearExpr.Sum(x) <= 1);
            }
        }
        // [END at_most_one_shift]

        // [START assign_nurses_evenly]
        // Try to distribute the shifts evenly, so that each nurse works
        // minShiftsPerNurse shifts. If this is not possible, because the total
        // number of shifts is not divisible by the number of nurses, some nurses will
        // be assigned one more shift.
        int minShiftsPerNurse = (numShifts * numDays) / numNurses;
        int maxShiftsPerNurse;

        if ((numShifts * numDays) % numNurses == 0)
        {
            maxShiftsPerNurse = minShiftsPerNurse;
        }
        else
        {
            maxShiftsPerNurse = minShiftsPerNurse + 1;
        }
        foreach (int n in allNurses)
        {
            IntVar[] numShiftsWorked = new IntVar[numDays * numShifts];
            foreach (int d in allDays)
            {
                foreach (int s in allShifts)
                {
                    var key = Tuple.Create(n, d, s);
                    numShiftsWorked[d * numShifts + s] = shifts[key];
                }
            }
            model.AddLinearConstraint(LinearExpr.Sum(numShiftsWorked), minShiftsPerNurse, maxShiftsPerNurse);
        }
        // [END assign_nurses_evenly]

        // [START objective]
        IntVar[] flatShifts        = new IntVar[numNurses * numDays * numShifts];
        int[]    flatShiftRequests = new int[numNurses * numDays * numShifts];
        foreach (int n in allNurses)
        {
            foreach (int d in allDays)
            {
                foreach (int s in allShifts)
                {
                    var key = Tuple.Create(n, d, s);
                    flatShifts[n * numDays * numShifts + d * numShifts + s]        = shifts[key];
                    flatShiftRequests[n * numDays * numShifts + d * numShifts + s] = shiftRequests[n, d, s];
                }
            }
        }
        model.Maximize(LinearExpr.ScalProd(flatShifts, flatShiftRequests));
        // [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:");
            foreach (int d in allDays)
            {
                Console.WriteLine($"Day {d}");
                foreach (int n in allNurses)
                {
                    bool isWorking = false;
                    foreach (int s in allShifts)
                    {
                        var key = Tuple.Create(n, d, s);
                        if (solver.Value(shifts[key]) == 1L)
                        {
                            if (shiftRequests[n, d, s] == 1)
                            {
                                Console.WriteLine($"  Nurse {n} work shift {s} (requested).");
                            }
                            else
                            {
                                Console.WriteLine($"  Nurse {n} work shift {s} (not requested).");
                            }
                        }
                    }
                }
            }
            Console.WriteLine(
                $"Number of shift requests met = {solver.ObjectiveValue} (out of {numNurses * minShiftsPerNurse}).");
        }
        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 #12
0
    // [END solution_printer]

    public static void Main(String[] args)
    {
        // [START data]
        const int numNurses = 4;
        const int numDays   = 3;
        const int numShifts = 3;

        int[] allNurses = Enumerable.Range(0, numNurses).ToArray();
        int[] allDays   = Enumerable.Range(0, numDays).ToArray();
        int[] allShifts = Enumerable.Range(0, numShifts).ToArray();
        // [END data]

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

        // Creates shift variables.
        // shifts[(n, d, s)]: nurse 'n' works shift 's' on day 'd'.
        // [START variables]
        Dictionary <Tuple <int, int, int>, IntVar> shifts = new Dictionary <Tuple <int, int, int>, IntVar>();

        foreach (int n in allNurses)
        {
            foreach (int d in allDays)
            {
                foreach (int s in allShifts)
                {
                    shifts.Add(Tuple.Create(n, d, s), model.NewBoolVar($"shifts_n{n}d{d}s{s}"));
                }
            }
        }
        // [END variables]

        // Each shift is assigned to exactly one nurse in the schedule period.
        // [START exactly_one_nurse]
        foreach (int d in allDays)
        {
            foreach (int s in allShifts)
            {
                IntVar[] x = new IntVar[numNurses];
                foreach (int n in allNurses)
                {
                    var key = Tuple.Create(n, d, s);
                    x[n] = shifts[key];
                }
                model.Add(LinearExpr.Sum(x) == 1);
            }
        }
        // [END exactly_one_nurse]

        // Each nurse works at most one shift per day.
        // [START at_most_one_shift]
        foreach (int n in allNurses)
        {
            foreach (int d in allDays)
            {
                IntVar[] x = new IntVar[numShifts];
                foreach (int s in allShifts)
                {
                    var key = Tuple.Create(n, d, s);
                    x[s] = shifts[key];
                }
                model.Add(LinearExpr.Sum(x) <= 1);
            }
        }
        // [END at_most_one_shift]

        // [START assign_nurses_evenly]
        // Try to distribute the shifts evenly, so that each nurse works
        // minShiftsPerNurse shifts. If this is not possible, because the total
        // number of shifts is not divisible by the number of nurses, some nurses will
        // be assigned one more shift.
        int minShiftsPerNurse = (numShifts * numDays) / numNurses;
        int maxShiftsPerNurse;

        if ((numShifts * numDays) % numNurses == 0)
        {
            maxShiftsPerNurse = minShiftsPerNurse;
        }
        else
        {
            maxShiftsPerNurse = minShiftsPerNurse + 1;
        }
        foreach (int n in allNurses)
        {
            IntVar[] numShiftsWorked = new IntVar[numDays * numShifts];
            foreach (int d in allDays)
            {
                foreach (int s in allShifts)
                {
                    var key = Tuple.Create(n, d, s);
                    numShiftsWorked[d * numShifts + s] = shifts[key];
                }
            }
            model.AddLinearConstraint(LinearExpr.Sum(numShiftsWorked), minShiftsPerNurse, maxShiftsPerNurse);
        }
        // [END assign_nurses_evenly]

        // [START parameters]
        CpSolver solver = new CpSolver();

        solver.StringParameters += "linearization_level:0 ";
        // Tell the solver to enumerate all solutions.
        solver.StringParameters += "enumerate_all_solutions:true ";
        // [END parameters]

        // Display the first five solutions.
        // [START solution_printer_instantiate]
        const int       solutionLimit = 5;
        SolutionPrinter cb            = new SolutionPrinter(allNurses, allDays, allShifts, shifts, solutionLimit);
        // [END solution_printer_instantiate]

        // Solve
        // [START solve]
        CpSolverStatus status = solver.Solve(model, cb);

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

        // [START statistics]
        Console.WriteLine("Statistics");
        Console.WriteLine($"  conflicts: {solver.NumConflicts()}");
        Console.WriteLine($"  branches : {solver.NumBranches()}");
        Console.WriteLine($"  wall time: {solver.WallTime()}s");
        // [END statistics]
    }
    public static void Main(String[] args)
    {
        // Data.
        // [START data]
        int[,] costs =
        {
            {  90,  76,  75,  70,  50,  74,  12, 68 }, { 35,  85,  55,  65,  48, 101,  70, 83 },
            { 125,  95,  90, 105,  59, 120,  36, 73 }, { 45, 110,  95, 115, 104,  83,  37, 71 },
            {  60, 105,  80,  75,  59,  62,  93, 88 }, { 45,  65, 110,  95,  47,  31,  81, 34 },
            {  38,  51, 107,  41,  69,  99, 115, 48 }, { 47,  85,  57,  71,  92,  77, 109, 36 },
            {  39,  63,  97,  49, 118,  56,  92, 61 }, { 47, 101,  71,  60,  88, 109,  52, 90 },
        };
        int numWorkers = costs.GetLength(0);
        int numTasks   = costs.GetLength(1);

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

        int[] taskSizes = { 10, 7, 3, 12, 15, 4, 11, 5 };
        // Maximum total of task sizes for any worker
        int totalSizeMax = 15;
        // [END data]

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

        // [END model]

        // Variables.
        // [START variables]
        BoolVar[,] x = new BoolVar[numWorkers, numTasks];
        foreach (int worker in allWorkers)
        {
            foreach (int task in allTasks)
            {
                x[worker, task] = model.NewBoolVar($"x[{worker},{task}]");
            }
        }
        // [END variables]

        // Constraints
        // [START constraints]
        // Each worker is assigned to at most max task size.
        foreach (int worker in allWorkers)
        {
            BoolVar[] vars = new BoolVar[numTasks];
            foreach (int task in allTasks)
            {
                vars[task] = x[worker, task];
            }
            model.Add(LinearExpr.WeightedSum(vars, taskSizes) <= totalSizeMax);
        }

        // Each task is assigned to exactly one worker.
        foreach (int task in allTasks)
        {
            List <ILiteral> workers = new List <ILiteral>();
            foreach (int worker in allWorkers)
            {
                workers.Add(x[worker, task]);
            }
            model.AddExactlyOne(workers);
        }
        // [END constraints]

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

        foreach (int worker in allWorkers)
        {
            foreach (int task in allTasks)
            {
                obj.AddTerm(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");
            foreach (int worker in allWorkers)
            {
                foreach (int task in allTasks)
                {
                    if (solver.Value(x[worker, task]) > 0.5)
                    {
                        Console.WriteLine($"Worker {worker} assigned to task {task}. " +
                                          $"Cost: {costs[worker, task]}");
                    }
                }
            }
        }
        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 #14
0
    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");
    }
Example #15
0
    public static void Main(String[] args)
    {
        // Data.
        // [START data]
        int[,] costs =
        {
            { 90,  76,  75,  70,  50,  74 }, { 35,  85,  55, 65, 48, 101 }, { 125, 95,  90, 105,  59, 120 },
            { 45, 110,  95, 115, 104,  83 }, { 60, 105,  80, 75, 59,  62 }, {  45, 65, 110,  95,  47,  31 },
            { 38,  51, 107,  41,  69,  99 }, { 47,  85,  57, 71, 92,  77 }, {  39, 63,  97,  49, 118,  56 },
            { 47, 101,  71,  60,  88, 109 }, { 17,  39, 103, 64, 61,  92 }, { 101, 45,  83,  59,  92,  27 },
        };
        int numWorkers = costs.GetLength(0);
        int numTasks   = costs.GetLength(1);

        int[] allWorkers = Enumerable.Range(0, numWorkers).ToArray();
        int[] allTasks   = Enumerable.Range(0, numTasks).ToArray();
        // [END data]

        // Allowed groups of workers:
        // [START allowed_groups]
        long[,] group1 =
        {
            { 0, 0, 1, 1 }, // Workers 2, 3
            { 0, 1, 0, 1 }, // Workers 1, 3
            { 0, 1, 1, 0 }, // Workers 1, 2
            { 1, 1, 0, 0 }, // Workers 0, 1
            { 1, 0, 1, 0 }, // Workers 0, 2
        };

        long[,] group2 =
        {
            { 0, 0, 1, 1 }, // Workers 6, 7
            { 0, 1, 0, 1 }, // Workers 5, 7
            { 0, 1, 1, 0 }, // Workers 5, 6
            { 1, 1, 0, 0 }, // Workers 4, 5
            { 1, 0, 0, 1 }, // Workers 4, 7
        };

        long[,] group3 =
        {
            { 0, 0, 1, 1 }, // Workers 10, 11
            { 0, 1, 0, 1 }, // Workers 9, 11
            { 0, 1, 1, 0 }, // Workers 9, 10
            { 1, 0, 1, 0 }, // Workers 8, 10
            { 1, 0, 0, 1 }, // Workers 8, 11
        };
        // [END allowed_groups]

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

        // [END model]

        // Variables.
        // [START variables]
        BoolVar[,] x = new BoolVar[numWorkers, numTasks];
        // Variables in a 1-dim array.
        foreach (int worker in allWorkers)
        {
            foreach (int task in allTasks)
            {
                x[worker, task] = model.NewBoolVar($"x[{worker},{task}]");
            }
        }
        // [END variables]

        // Constraints
        // [START constraints]
        // Each worker is assigned to at most one task.
        foreach (int worker in allWorkers)
        {
            List <ILiteral> tasks = new List <ILiteral>();
            foreach (int task in allTasks)
            {
                tasks.Add(x[worker, task]);
            }
            model.AddAtMostOne(tasks);
        }

        // Each task is assigned to exactly one worker.
        foreach (int task in allTasks)
        {
            List <ILiteral> workers = new List <ILiteral>();
            foreach (int worker in allWorkers)
            {
                workers.Add(x[worker, task]);
            }
            model.AddExactlyOne(workers);
        }
        // [END constraints]

        // [START assignments]
        // Create variables for each worker, indicating whether they work on some task.
        BoolVar[] work = new BoolVar[numWorkers];
        foreach (int worker in allWorkers)
        {
            work[worker] = model.NewBoolVar($"work[{worker}]");
        }

        foreach (int worker in allWorkers)
        {
            List <ILiteral> tasks = new List <ILiteral>();
            foreach (int task in allTasks)
            {
                tasks.Add(x[worker, task]);
            }
            model.Add(work[worker] == LinearExpr.Sum(tasks));
        }

        // Define the allowed groups of worders
        model.AddAllowedAssignments(new IntVar[] { work[0], work[1], work[2], work[3] }).AddTuples(group1);
        model.AddAllowedAssignments(new IntVar[] { work[4], work[5], work[6], work[7] }).AddTuples(group2);
        model.AddAllowedAssignments(new IntVar[] { work[8], work[9], work[10], work[11] }).AddTuples(group3);
        // [END assignments]

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

        foreach (int worker in allWorkers)
        {
            foreach (int task in allTasks)
            {
                obj.AddTerm(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");
            foreach (int worker in allWorkers)
            {
                foreach (int task in allTasks)
                {
                    if (solver.Value(x[worker, task]) > 0.5)
                    {
                        Console.WriteLine($"Worker {worker} assigned to task {task}. " +
                                          $"Cost: {costs[worker, task]}");
                    }
                }
            }
        }
        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 #16
0
    public static void Main(String[] args)
    {
        // Data.
        // [START data]
        int[,] costs =
        {
            { 90,  76, 75,  70 }, { 35,  85, 55, 65 }, { 125, 95,  90, 105 },
            { 45, 110, 95, 115 }, { 60, 105, 80, 75 }, {  45, 65, 110,  95 },
        };
        int numWorkers = costs.GetLength(0);
        int numTasks   = costs.GetLength(1);

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

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

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

        // [END model]

        // Variables.
        // [START variables]
        BoolVar[,] x = new BoolVar[numWorkers, numTasks];
        foreach (int worker in allWorkers)
        {
            foreach (int task in allTasks)
            {
                x[worker, task] = model.NewBoolVar($"x[{worker},{task}]");
            }
        }
        // [END variables]

        // Constraints
        // [START constraints]
        // Each worker is assigned to at most one task.
        foreach (int worker in allWorkers)
        {
            List <ILiteral> tasks = new List <ILiteral>();
            foreach (int task in allTasks)
            {
                tasks.Add(x[worker, task]);
            }
            model.AddAtMostOne(tasks);
        }

        // Each task is assigned to exactly one worker.
        foreach (int task in allTasks)
        {
            List <ILiteral> workers = new List <ILiteral>();
            foreach (int worker in allWorkers)
            {
                workers.Add(x[worker, task]);
            }
            model.AddExactlyOne(workers);
        }

        // Each team takes at most two tasks.
        List <IntVar> team1Tasks = new List <IntVar>();

        foreach (int worker in team1)
        {
            foreach (int task in allTasks)
            {
                team1Tasks.Add(x[worker, task]);
            }
        }
        model.Add(LinearExpr.Sum(team1Tasks.ToArray()) <= teamMax);

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

        foreach (int worker in team2)
        {
            foreach (int task in allTasks)
            {
                team2Tasks.Add(x[worker, task]);
            }
        }
        model.Add(LinearExpr.Sum(team2Tasks.ToArray()) <= teamMax);
        // [END constraints]

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

        foreach (int worker in allWorkers)
        {
            foreach (int task in allTasks)
            {
                obj.AddTerm(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");
            foreach (int worker in allWorkers)
            {
                foreach (int task in allTasks)
                {
                    if (solver.Value(x[worker, task]) > 0.5)
                    {
                        Console.WriteLine($"Worker {worker} assigned to task {task}. " +
                                          $"Cost: {costs[worker, task]}");
                    }
                }
            }
        }
        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");
    }