예제 #1
0
 public void Sequence() {
   Solver solver = new Solver("Solver");
   IntervalVar[] intervals =
     solver.MakeFixedDurationIntervalVarArray(10, 0, 10, 5, false, "task");
   DisjunctiveConstraint disjunctive = intervals.Disjunctive("Sequence");
   SequenceVar var = disjunctive.SequenceVar();
   Assignment ass = solver.MakeAssignment();
   ass.Add(var);
   ass.SetForwardSequence(var, new int[] { 1, 3, 5 });
   int[] seq = ass.ForwardSequence(var);
   Assert.Equal(3, seq.Length);
 }
예제 #2
0
    private static void Solve(int first_slot)
    {
        Console.WriteLine("----------------------------------------------------");
        Solver solver = new Solver("SpeakerScheduling");

        // the slots each speaker is available
        int[][] speaker_availability =
        {
            new int[] {  1,  3,  4,  6,  7, 10, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 54, 55, 56, 57, 58, 59 },
            new int[] {  1,  2,  7,  8, 10, 11, 16, 17, 18, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 49, 52, 53, 54, 55, 56, 57, 58, 59,60 },
            new int[] {  5,  6,  7, 10, 12, 14, 16, 17, 21, 22, 23, 24, 33, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 51, 53, 55, 56, 57, 58,59 },
            new int[] {  1,  2,  3,  4,  5,  6,  7, 11, 13, 14, 15, 16, 20, 24, 25, 33, 34, 35, 37, 38, 39, 40, 41, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 58, 59,60 },
            new int[] {  4,  7,  8,  9, 16, 17, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 49, 50, 51, 53, 55, 56, 57, 58, 59,60 },
            new int[] {  4,  7,  9, 11, 12, 13, 14, 15, 16, 17, 18, 22, 23, 24, 33, 34, 35, 36, 38, 39, 42, 44, 46, 48, 49, 51, 53, 54, 55, 56,57 },
            new int[] {  1,  2,  3,  4,  5,  6,  7, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 54, 55, 56, 57, 58, 59,60 },
            new int[] {  1,  3, 11, 14, 15, 16, 17, 21, 22, 23, 24, 25, 33, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 51, 52, 53, 54, 55, 56, 57, 58, 59,60 },
            new int[] {  1,  2,  3,  4,  5,  7,  8,  9, 10, 11, 13, 18, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52, 53, 54, 55, 56, 57, 59,60 },
            new int[] { 24, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,60 },
            new int[] {  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53,55, 56, 57, 58, 59, 60 },
            new int[] {  3,  4,  5,  6, 13, 15, 16, 17, 18, 19, 21, 22, 24, 25, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 47, 52, 53, 55, 57, 58, 59,60 },
            new int[] {  4,  5,  6,  8, 11, 12, 13, 14, 17, 19, 20, 22, 23, 24, 25, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 47, 48, 49, 50, 51, 52, 55, 56,57 },
            new int[] {  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,52, 53, 54, 55, 56, 57, 58, 59, 60 },
            new int[] { 12, 25, 33, 35, 36, 37, 39, 41, 42, 43, 48, 51, 52, 53, 54, 57, 59,60 },
            new int[] {  4,  8, 16, 17, 19, 23, 25, 33, 34, 35, 37, 41, 44, 45, 47, 48, 49,50 },
            new int[] {  3, 23, 24, 25, 33, 35, 36, 37, 38, 39, 40, 42, 43, 44, 49, 50, 53, 54, 55, 56, 57, 58,60 },
            new int[] {  7, 13, 19, 20, 22, 23, 24, 25, 33, 34, 35, 38, 40, 41, 42, 44, 45, 46, 47, 48, 49, 52, 53, 54, 58, 59, 60 }
        };

        // how long each talk lasts for each speaker
        int[] durations        = { 1, 2, 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
        int   sum_of_durations = durations.Sum();

        int number_of_speakers = durations.Length;
        // calculate the total number of slots (maximum in the availability array)
        // (and add the max durations)
        int last_slot = (from s in Enumerable.Range(0, number_of_speakers)
                         select speaker_availability[s].Max()).Max();

        Console.WriteLine(
            "Scheduling {0} speakers, for a total of {1} slots, during [{2}..{3}]",
            number_of_speakers, sum_of_durations, first_slot, last_slot);

        // Start variable for all talks.
        IntVar[] starts = new IntVar[number_of_speakers];
        // We store the possible starts for all talks filtered from the
        // duration and the speaker availability.
        int[][] possible_starts = new int[number_of_speakers][];

        for (int speaker = 0; speaker < number_of_speakers; ++speaker)
        {
            int duration = durations[speaker];
            // Let's filter the possible starts.
            List <int> filtered_starts = new List <int>();
            int        availability    = speaker_availability[speaker].Length;
            for (int index = 0; index < availability; ++index)
            {
                bool ok   = true;
                int  slot = speaker_availability[speaker][index];
                if (slot < first_slot)
                {
                    continue;
                }
                for (int offset = 1; offset < durations[speaker]; ++offset)
                {
                    if (index + offset >= availability ||
                        speaker_availability[speaker][index + offset] != slot + offset)
                    {
                        // discontinuity.
                        ok = false;
                        break;
                    }
                }
                if (ok)
                {
                    filtered_starts.Add(slot);
                }
                possible_starts[speaker] = filtered_starts.ToArray();
            }
            starts[speaker] =
                solver.MakeIntVar(possible_starts[speaker], "start[" + speaker + "]");
        }

        List <IntVar>[] contributions_per_slot =
            new List <IntVar> [last_slot + 1];
        for (int slot = first_slot; slot <= last_slot; ++slot)
        {
            contributions_per_slot[slot] = new List <IntVar>();
        }
        for (int speaker = 0; speaker < number_of_speakers; ++speaker)
        {
            int    duration  = durations[speaker];
            IntVar start_var = starts[speaker];
            foreach (int start in possible_starts[speaker])
            {
                for (int offset = 0; offset < duration; ++offset)
                {
                    contributions_per_slot[start + offset].Add(start_var.IsEqual(start));
                }
            }
        }
        // Force the schedule to be consistent.
        for (int slot = first_slot; slot <= last_slot; ++slot)
        {
            solver.Add(
                solver.MakeSumLessOrEqual(contributions_per_slot[slot].ToArray(), 1));
        }

        // Add minimum start info.
        for (int speaker = 0; speaker < number_of_speakers; ++speaker)
        {
            solver.Add(starts[speaker] >= first_slot);
        }

        // Creates makespan.
        IntVar[] end_times = new IntVar[number_of_speakers];
        for (int speaker = 0; speaker < number_of_speakers; speaker++)
        {
            end_times[speaker] = (starts[speaker] + (durations[speaker] - 1)).Var();
        }
        IntVar last_slot_var = end_times.Max().VarWithName("last_slot");

        // Add trivial bound to objective.
        last_slot_var.SetMin(first_slot + sum_of_durations - 1);

        // Redundant scheduling constraint.
        IntervalVar[] intervals =
            solver.MakeFixedDurationIntervalVarArray(starts, durations, "intervals");
        DisjunctiveConstraint disjunctive =
            solver.MakeDisjunctiveConstraint(intervals, "disjunctive");

        solver.Add(disjunctive);

        //
        // Search
        //
        List <IntVar> short_talks = new List <IntVar>();
        List <IntVar> long_talks  = new List <IntVar>();

        for (int speaker = 0; speaker < number_of_speakers; ++speaker)
        {
            if (durations[speaker] == 1)
            {
                short_talks.Add(starts[speaker]);
            }
            else
            {
                long_talks.Add(starts[speaker]);
            }
        }
        OptimizeVar     objective_monitor = solver.MakeMinimize(last_slot_var, 1);
        DecisionBuilder long_phase        =
            solver.MakePhase(long_talks.ToArray(),
                             Solver.CHOOSE_MIN_SIZE_LOWEST_MIN,
                             Solver.ASSIGN_MIN_VALUE);
        DecisionBuilder short_phase =
            new FlowAssign(short_talks.ToArray(), first_slot, last_slot_var);
        DecisionBuilder obj_phase =
            solver.MakePhase(last_slot_var,
                             Solver.CHOOSE_FIRST_UNBOUND,
                             Solver.ASSIGN_MIN_VALUE);
        DecisionBuilder main_phase =
            solver.Compose(long_phase, short_phase, obj_phase);

        solver.NewSearch(main_phase, objective_monitor);
        while (solver.NextSolution())
        {
            Console.WriteLine("\nLast used slot: " + (last_slot_var.Value()));
            Console.WriteLine("Speakers (start..end):");
            for (int s = 0; s < number_of_speakers; s++)
            {
                long sstart = starts[s].Value();
                Console.WriteLine("  - speaker {0,2}: {1,2}..{2,2}", (s + 1),
                                  sstart, (sstart + durations[s] - 1));
            }
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());
        solver.EndSearch();
    }
예제 #3
0
파일: issue33.cs 프로젝트: ashkaps/or-tools
        private void Model()
        {
            /* Building basic task data structures */
            for (int i = 0; i < tasks.Length; i++)
            {
                /* Create a new set of possible IntervalVars & IntVar to decide
                 * which one (and only 1) is performed */
                taskStructures[i] = new TaskAlternative(tasks[i]);

                /* Container to use when posting constraints */
                location2Task[tasks[i].LocationId][tasks[i].TaskPosition] = taskStructures[i];

                /* Get task type */
                int taskType = tasks[i].TaskType;

                /* Possible tool for this task */
                List <Tool> tools    = taskType2Tool[taskType];
                bool        optional = tools.Count > 1;

                /* List of boolean variables. If performedOnTool[t] == true then
                 * the task is performed on tool t */
                List <IntVar> performedOnTool = new List <IntVar>();
                for (int t = 0; t < tools.Count; t++)
                {
                    /* Creating an IntervalVar. If tools.Count > 1 the intervalVar
                     * is *OPTIONAL* */
                    int toolId = tools[t].Id;
                    Debug.Assert(tasks[i].Durations.ContainsKey(toolId));
                    int    duration = tasks[i].Durations[toolId];
                    string name     = "J " + tasks[i].Id + " [" + toolId + "]";

                    IntervalVar intervalVar;
                    if (taskType == factoryData.Inspection)
                    {
                        /* We set a 0 time if the task is an inspection */
                        duration    = 0;
                        intervalVar = solver.MakeFixedDurationIntervalVar(0, horizon, duration, optional, name);
                        IntVar start = intervalVar.SafeStartExpr(-1).Var();

                        intervalVar.SafeStartExpr(-1).Var().SetValues(factoryData.InspectionStarts);
                    }
                    else
                    {
                        intervalVar = solver.MakeFixedDurationIntervalVar(0, horizon, duration, optional, name);
                    }

                    taskStructures[i].Intervals.Add(intervalVar);
                    tool2Task[toolId].Add(intervalVar);
                    toolIntervalVar2TaskId[toolId].Add(i);

                    /* Collecting all the bool vars, even if they are optional */
                    performedOnTool.Add(intervalVar.PerformedExpr().Var());
                }

                /* Linking the bool var to a single integer variable: */
                /* if alternativeToolVar == t <=> performedOnTool[t] == true */
                string alternativeName    = "J " + tasks[i].Id;
                IntVar alternativeToolVar = solver.MakeIntVar(0, tools.Count - 1, alternativeName);
                taskStructures[i].ToolVar = alternativeToolVar;

                solver.Add(solver.MakeMapDomain(alternativeToolVar, performedOnTool.ToArray()));
                Debug.Assert(performedOnTool.ToArray().Length == alternativeToolVar.Max() + 1);

                selectedTool.Add(alternativeToolVar);
            }

            /* Creates precedences on a work Location in order to enforce a
             * fully ordered set within the same location
             */
            for (int d = 0; d < location2Task.Length; d++)
            {
                for (int i = 0; i < location2Task[d].Length - 1; i++)
                {
                    TaskAlternative task1 = location2Task[d][i];
                    TaskAlternative task2 = location2Task[d][i + 1];
                    /* task1 must end before task2 starts */
                    /* Adding precedence for each possible alternative pair */
                    for (int t1 = 0; t1 < task1.Intervals.Count(); t1++)
                    {
                        IntervalVar task1Alternative = task1.Intervals[t1];
                        for (int t2 = 0; t2 < task2.Intervals.Count(); t2++)
                        {
                            IntervalVar task2Alternative = task2.Intervals[t2];
                            Constraint  precedence       = solver.MakeIntervalVarRelation(
                                task2Alternative, Solver.STARTS_AFTER_END, task1Alternative);
                            solver.Add(precedence);
                        }
                    }
                }
            }

            /* Adds disjunctive constraints on unary resources, and creates
             * sequence variables. */
            for (int t = 0; t < factoryData.NbTools; t++)
            {
                string name = "Tool " + t;

                if (!factoryData.Tools[t].CanPerformTaskType(factoryData.Inspection))
                {
                    DisjunctiveConstraint ct = solver.MakeDisjunctiveConstraint(tool2Task[t].ToArray(), name);
                    solver.Add(ct);
                    allToolSequences[t] = ct.SequenceVar();
                }
                PostTransitionTimeConstraints(t, true);
            }

            /* Collecting all tasks end for makespan objective function */
            List <IntVar> intervalEnds = new List <IntVar>();

            for (int i = 0; i < tasks.Length; i++)
            {
                foreach (IntervalVar var in taskStructures[i].Intervals)
                {
                    intervalEnds.Add(var.SafeEndExpr(-1).Var());
                }
            }

            /* Objective: minimize the makespan (maximum end times of all tasks) */
            makespan  = solver.MakeMax(intervalEnds.ToArray()).Var();
            objective = solver.MakeMinimize(makespan, 1);
        }
    /**
     *
     *
     * Organizing a day.
     *
     * Simple scheduling problem.
     *
     * Problem formulation from ECLiPSe:
     * Slides on (Finite Domain) Constraint Logic Programming, page 38f
     * http://eclipseclp.org/reports/eclipse.ppt
     *
     *
     * Also see http://www.hakank.org/google_or_tools/organize_day.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("OrganizeDayIntervals");

        int n = 4;

        int work = 0;
        int mail = 1;
        int shop = 2;
        int bank = 3;
        // the valid times of the day
        int begin = 9;
        int end   = 17;

        // tasks
        int[] tasks = { work, mail, shop, bank };
        // durations
        int[] durations = { 4, 1, 2, 1 };
        // Arrays for interval variables.
        int[] starts_max = { begin, begin, begin, begin };
        int[] ends_max   = { end - 4, end - 1, end - 2, end - 1 };

        // task [i,0] must be finished before task [i,1]
        int[,] before_tasks = { { bank, shop }, { mail, work } };

        //
        // Decision variables
        //
        IntervalVar[] intervals =
            solver.MakeFixedDurationIntervalVarArray(n, starts_max, ends_max, durations, false, "task");
        //
        // Constraints
        //
        DisjunctiveConstraint disjunctive = intervals.Disjunctive("Sequence");

        solver.Add(disjunctive);

        // specific constraints
        for (int t = 0; t < before_tasks.GetLength(0); t++)
        {
            int before = before_tasks[t, 0];
            int after  = before_tasks[t, 1];
            solver.Add(intervals[after].StartsAfterEnd(intervals[before]));
        }

        solver.Add(intervals[work].StartsAfter(11));

        //
        // Search
        //
        SequenceVar var = disjunctive.SequenceVar();

        SequenceVar[]   seq_array = new SequenceVar[] { var };
        DecisionBuilder db        = solver.MakePhase(seq_array, Solver.SEQUENCE_DEFAULT);

        solver.NewSearch(db);

        while (solver.NextSolution())
        {
            foreach (int t in tasks)
            {
                Console.WriteLine(intervals[t].ToString());
            }
            Console.WriteLine();
        }

        Console.WriteLine("\nSolutions: {0}", solver.Solutions());
        Console.WriteLine("WallTime: {0}ms", solver.WallTime());
        Console.WriteLine("Failures: {0}", solver.Failures());
        Console.WriteLine("Branches: {0} ", solver.Branches());

        solver.EndSearch();
    }
예제 #5
0
        static void Main(string[] args)
        {
            InitTaskList();
            int taskCount = GetTaskCount();

            Solver solver = new Solver("ResourceConstraintScheduling");

            IntervalVar[] tasks       = new IntervalVar[taskCount];
            IntVar[]      taskChoosed = new IntVar[taskCount];
            IntVar[]      makeSpan    = new IntVar[GetEndTaskCount()];

            int endJobCounter = 0;

            foreach (Job j in myJobList)
            {
                IntVar[] tmp = new IntVar[j.AlternativeTasks.Count];
                int      i   = 0;
                foreach (Task t in j.AlternativeTasks)
                {
                    long ti = taskIndexes[t.Name];
                    taskChoosed[ti] = solver.MakeIntVar(0, 1, t.Name + "_choose");
                    tmp[i++]        = taskChoosed[ti];
                    tasks[ti]       = solver.MakeFixedDurationIntervalVar(
                        0, 100000, t.Duration, false, t.Name + "_interval");
                    if (j.Successor == null)
                    {
                        makeSpan[endJobCounter++] = tasks[ti].EndExpr().Var();
                    }
                    if (!tasksToEquipment.ContainsKey(t.Equipment))
                    {
                        tasksToEquipment[t.Equipment] = new List <IntervalVar>();
                    }
                    tasksToEquipment[t.Equipment].Add(tasks[ti]);
                }
                solver.Add(IntVarArrayHelper.Sum(tmp) == 1);
            }

            List <SequenceVar> all_seq = new List <SequenceVar>();

            foreach (KeyValuePair <long, List <IntervalVar> > pair in tasksToEquipment)
            {
                DisjunctiveConstraint dc = solver.MakeDisjunctiveConstraint(
                    pair.Value.ToArray(), pair.Key.ToString());
                solver.Add(dc);
                all_seq.Add(dc.SequenceVar());
            }

            IntVar      objective_var     = solver.MakeMax(makeSpan).Var();
            OptimizeVar objective_monitor = solver.MakeMinimize(objective_var, 1);

            DecisionBuilder sequence_phase =
                solver.MakePhase(all_seq.ToArray(), Solver.SEQUENCE_DEFAULT);
            DecisionBuilder objective_phase =
                solver.MakePhase(objective_var, Solver.CHOOSE_FIRST_UNBOUND,
                                 Solver.ASSIGN_MIN_VALUE);
            DecisionBuilder main_phase = solver.Compose(sequence_phase, objective_phase);

            const int     kLogFrequency = 1000000;
            VoidToString  prefix        = new Prefix();
            SearchMonitor search_log    =
                solver.MakeSearchLog(kLogFrequency, objective_monitor, prefix);

            SolutionCollector collector = solver.MakeLastSolutionCollector();

            collector.Add(all_seq.ToArray());
            collector.AddObjective(objective_var);

            if (solver.Solve(main_phase, search_log, objective_monitor, null, collector))
            {
                Console.Out.WriteLine("Optimal solution = " + collector.ObjectiveValue(0));
            }
            else
            {
                Console.Out.WriteLine("No solution.");
            }
        }
예제 #6
0
파일: JobShop.cs 프로젝트: wsgan001/TPM
    public void RunJobShopScheduling(String solverType)
    {
        Solver solver = new Solver(solverType);

        if (solver == null)
        {
            Console.WriteLine("JobShop failed to create a solver " + solverType);
            return;
        }

        // All tasks
        Dictionary <string, IntervalVar> allTasks = new Dictionary <string, IntervalVar>();

        // Creates jobs
        for (int i = 0; i < allJobs.Count; i++)
        {
            for (int j = 0; j < machines.ElementAt(i).Count; j++)
            {
                IntervalVar oneTask = solver.MakeFixedDurationIntervalVar(0,
                                                                          horizon,
                                                                          processingTimes.ElementAt(i).ElementAt(j),
                                                                          false,
                                                                          "Job_" + i + "_" + j);
                //Console.WriteLine("Job_" + i + "_" + j);
                allTasks.Add("Job_" + i + "_" + j, oneTask);
            }
        }

        // Create sequence variables and add disjuctive constraints
        List <SequenceVar> allSequences = new List <SequenceVar>();

        foreach (var machine in allMachines)
        {
            List <IntervalVar> machinesJobs = new List <IntervalVar>();
            for (int i = 0; i < allJobs.Count; i++)
            {
                for (int k = 0; k < machines.ElementAt(i).Count; k++)
                {
                    if (machines.ElementAt(i).ElementAt(k) == machine)
                    {
                        machinesJobs.Add(allTasks["Job_" + i + "_" + k]);
                    }
                }
            }

            DisjunctiveConstraint disj = solver.MakeDisjunctiveConstraint(machinesJobs.ToArray(),
                                                                          "machine " + machine);
            allSequences.Add(disj.SequenceVar());
            solver.Add(disj);
        }

        // Add conjunctive constraints
        foreach (var job in allJobs)
        {
            for (int j = 0; j < machines.ElementAt(job).Count - 1; j++)
            {
                solver.Add(allTasks["Job_" + job + "_" + (j + 1)].StartsAfterEnd(allTasks["Job_" + job + "_" + j]));
            }
        }

        // Set the objective
        IntVar[] allEnds = new IntVar[jobsCount];
        for (int i = 0; i < allJobs.Count; i++)
        {
            allEnds[i] = allTasks["Job_" + i + "_" + (machines.ElementAt(i).Count - 1)].EndExpr().Var();
        }

        // Objective: minimize the makespan (maximum end times of all tasks)
        // of the problem.
        IntVar      objectiveVar     = solver.MakeMax(allEnds).Var();
        OptimizeVar objectiveMonitor = solver.MakeMinimize(objectiveVar, 1);

        // Create search phases
        DecisionBuilder sequencePhase = solver.MakePhase(allSequences.ToArray(), Solver.SEQUENCE_DEFAULT);
        DecisionBuilder varsPhase     = solver.MakePhase(objectiveVar, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        // The main decision builder (ranks all tasks, then fixes the
        // objectiveVariable).
        DecisionBuilder mainPhase = solver.Compose(sequencePhase, varsPhase);

        SolutionCollector collector = solver.MakeLastSolutionCollector();

        collector.Add(allSequences.ToArray());
        collector.Add(objectiveVar);

        foreach (var i in allMachines)
        {
            SequenceVar sequence      = allSequences.ElementAt(i);
            long        sequenceCount = sequence.Size();
            for (int j = 0; j < sequenceCount; j++)
            {
                IntervalVar t = sequence.Interval(j);
                collector.Add(t.StartExpr().Var());
                collector.Add(t.EndExpr().Var());
            }
        }

        // Search.
        bool solutionFound = solver.Solve(mainPhase, null, objectiveMonitor, null, collector);

        if (solutionFound)
        {
            //The index of the solution from the collector
            const int  SOLUTION_INDEX = 0;
            Assignment solution       = collector.Solution(SOLUTION_INDEX);

            string solLine      = "";
            string solLineTasks = "";
            Console.WriteLine("Time Intervals for Tasks\n");

            List <List <TimeSpan> > tuplesSolution = new List <List <TimeSpan> >();

            for (int m = 0; m < this.machinesCount; m++)
            {
                //Console.WriteLine("MachineCount: " + this.machinesCount);
                solLine      = "Machine " + m + " :";
                solLineTasks = "Machine " + m + ": ";

                SequenceVar seq            = allSequences.ElementAt(m);
                int[]       storedSequence = collector.ForwardSequence(SOLUTION_INDEX, seq);

                foreach (int taskIndex in storedSequence)
                {
                    //Console.WriteLine("taskIndex: " + taskIndex);
                    IntervalVar task = seq.Interval(taskIndex);
                    solLineTasks += task.Name() + " ";
                    //Console.WriteLine("Len: " + storedSequence.Length);
                }

                // First GreenTime
                //TimeSpan timeToAdd = tuplesSolution.First().Last();
                TimeSpan timeEndBucket   = this.bucketInfo.EndBucket;
                TimeSpan timeStartBucket = this.bucketInfo.StartBucket;


                int  solutionSize = tuplesSolution.Count;
                bool isEnd        = false;

                List <int> list_id = jobIds.ElementAt(m);
                // Adding GreenTime to Solution
                while (timeStartBucket.CompareTo(timeEndBucket) < 0)
                {
                    foreach (int taskIndex in storedSequence)
                    {
                        IntervalVar task = seq.Interval(taskIndex);

                        var startValue = TimeSpan.FromSeconds(collector.Value(0, task.StartExpr().Var()));
                        var endValue   = TimeSpan.FromSeconds(collector.Value(0, task.EndExpr().Var()));

                        TimeSpan greenTime = endValue.Subtract(startValue);
                        TimeSpan timeEnd;

                        timeEnd = timeStartBucket.Add(greenTime);


                        List <TimeSpan> tuple = new List <TimeSpan>();
                        tuple.Add(timeStartBucket);
                        if (timeEndBucket.CompareTo(timeEnd) < 0)
                        {
                            timeEnd = timeEndBucket;
                            isEnd   = true;
                        }

                        tuple.Add(timeEnd);
                        tuplesSolution.Add(tuple);
                        if (taskIndex + 1 < list_id.Count() && list_id.ElementAt(taskIndex) == list_id.ElementAt(taskIndex + 1))
                        {
                            timeStartBucket = timeStartBucket.Add(TimeSpan.FromSeconds(this.cycleTime));
                        }
                        else
                        {
                            timeStartBucket = timeEnd;
                        }
                        if (isEnd)
                        {
                            break;
                        }
                    }
                }

                //
                // Saving the Solution to a XML file
                //
                JobShop.save(m, tuplesSolution);

                //solLine += "\n";
                //solLineTasks += "\n";

                //Console.WriteLine(solLineTasks);
                //Console.WriteLine(solLine);
            }
        }
        else
        {
            Console.WriteLine("No solution found!");
        }
    }
예제 #7
0
파일: JobShop.cs 프로젝트: wsgan001/TPM
    public void RunJobShopScheduling(String solverType)
    {
        Solver solver = new Solver(solverType);

        if (solver == null)
        {
            Console.WriteLine("JobShop failed to create a solver " + solverType);
            return;
        }

        // All tasks
        Dictionary <string, IntervalVar> allTasks = new Dictionary <string, IntervalVar>();

        // Creates jobs
        for (int i = 0; i < allJobs.Count; i++)
        {
            for (int j = 0; j < machines.ElementAt(i).Count; j++)
            {
                IntervalVar oneTask = solver.MakeFixedDurationIntervalVar(0,
                                                                          horizon,
                                                                          processingTimes.ElementAt(i).ElementAt(j),
                                                                          false,
                                                                          "Job_" + i + "_" + j);

                allTasks.Add("Job_" + i + "_" + j, oneTask);
            }
        }

        // Create sequence variables and add disjuctive constraints
        List <SequenceVar> allSequences = new List <SequenceVar>();

        foreach (var machine in allMachines)
        {
            List <IntervalVar> machinesJobs = new List <IntervalVar>();
            for (int i = 0; i < allJobs.Count; i++)
            {
                for (int k = 0; k < machines.ElementAt(i).Count; k++)
                {
                    if (machines.ElementAt(i).ElementAt(k) == machine)
                    {
                        machinesJobs.Add(allTasks["Job_" + i + "_" + k]);
                    }
                }
            }

            DisjunctiveConstraint disj = solver.MakeDisjunctiveConstraint(machinesJobs.ToArray(),
                                                                          "machine " + machine);
            allSequences.Add(disj.SequenceVar());
            solver.Add(disj);
        }

        // Add conjunctive constraints
        foreach (var job in allJobs)
        {
            for (int j = 0; j < machines.ElementAt(job).Count - 1; j++)
            {
                solver.Add(allTasks["Job_" + job + "_" + (j + 1)].StartsAfterEnd(allTasks["Job_" + job + "_" + j]));
            }
        }

        // Set the objective
        IntVar[] allEnds = new IntVar[jobsCount];
        for (int i = 0; i < allJobs.Count; i++)
        {
            allEnds[i] = allTasks["Job_" + i + "_" + (machines.ElementAt(i).Count - 1)].EndExpr().Var();
        }

        // Objective: minimize the makespan (maximum end times of all tasks)
        // of the problem.
        IntVar      objectiveVar     = solver.MakeMax(allEnds).Var();
        OptimizeVar objectiveMonitor = solver.MakeMinimize(objectiveVar, 1);

        // Create search phases
        DecisionBuilder sequencePhase = solver.MakePhase(allSequences.ToArray(), Solver.SEQUENCE_DEFAULT);
        DecisionBuilder varsPhase     = solver.MakePhase(objectiveVar, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        // The main decision builder (ranks all tasks, then fixes the
        // objectiveVariable).
        DecisionBuilder mainPhase = solver.Compose(sequencePhase, varsPhase);

        SolutionCollector collector = solver.MakeLastSolutionCollector();

        collector.Add(allSequences.ToArray());
        collector.Add(objectiveVar);

        foreach (var i in allMachines)
        {
            SequenceVar sequence      = allSequences.ElementAt(i);
            long        sequenceCount = sequence.Size();
            for (int j = 0; j < sequenceCount; j++)
            {
                IntervalVar t = sequence.Interval(j);
                collector.Add(t.StartExpr().Var());
                collector.Add(t.EndExpr().Var());
            }
        }

        // Search.
        bool solutionFound = solver.Solve(mainPhase, null, objectiveMonitor, null, collector);

        if (solutionFound)
        {
            //The index of the solution from the collector
            const int  SOLUTION_INDEX = 0;
            Assignment solution       = collector.Solution(SOLUTION_INDEX);

            string solLine      = "";
            string solLineTasks = "";
            Console.WriteLine("Time Intervals for Tasks\n");

            for (int m = 0; m < this.machinesCount; m++)
            {
                //Console.WriteLine("MachineCount: " + this.machinesCount);
                solLine      = "Machine " + m + " :";
                solLineTasks = "Machine " + m + ": ";

                SequenceVar seq            = allSequences.ElementAt(m);
                int[]       storedSequence = collector.ForwardSequence(SOLUTION_INDEX, seq);

                foreach (int taskIndex in storedSequence)
                {
                    //Console.WriteLine("taskIndex: " + taskIndex);
                    IntervalVar task = seq.Interval(taskIndex);
                    solLineTasks += task.Name() + " ";
                    //Console.WriteLine("Len: " + storedSequence.Length);
                }

                foreach (int taskIndex in storedSequence)
                {
                    IntervalVar task    = seq.Interval(taskIndex);
                    string      solTemp = "[" + collector.Value(0, task.StartExpr().Var()) + ",";
                    solTemp += collector.Value(0, task.EndExpr().Var()) + "] ";
                    solLine += solTemp;
                }

                //solLine += "\n";
                solLineTasks += "\n";

                //Console.WriteLine(solLineTasks);
                Console.WriteLine(solLine);
            }
        }
        else
        {
            Console.WriteLine("No solution found!");
        }
    }
예제 #8
0
        public static void Solve(FlexibleJobShopData data, bool chatty = false)
        {
            // Compute horizon
            var horizon = data.JobList.Sum(
                j => j.TaskList.Sum(
                    t => t.Durations.Max()));


            // ----- Create all intervals and vars -----

            /*
             * // Use some profiling and change the default parameters of the solver
             * SolverParameters solverParams = new SolverParameters();
             * // Change the profile level
             * solverParams.profile_level = SolverParameters.NORMAL_PROFILING;
             * // Constraint programming engine
             * Solver solver = new Solver("JobShop", solverParams);
             */
            // Constraint programming engine
            Solver solver = new Solver($"FlexibleJobShop: {data.Name}");

            // Initialize dictionaries to hold references to task intervals
            var tasksByJobId = new Dictionary <uint, List <TaskAlternative> >();

            foreach (var job in data.JobList)
            {
                tasksByJobId[job.Id] = new List <TaskAlternative>(job.TaskList.Count);
            }
            var tasksByMachineId = new Dictionary <uint, IntervalVarVector>();

            foreach (var machine in data.MachineList)
            {
                tasksByMachineId[machine.Id] = new IntervalVarVector();
            }

            // Creates all individual interval variables and collect in dictionaries
            foreach (var job in data.JobList)
            {
                foreach (var task in job.TaskList)
                {
                    var alternative = new TaskAlternative(job.Id);
                    tasksByJobId[job.Id].Add(alternative);
                    var activeVariables = new IntVarVector();
                    var hasAlternatives = task.AlternativesCount > 1;
                    for (int alt = 0; alt < task.AlternativesCount; alt++)
                    {
                        var         machine  = task.Machines[alt];
                        var         duration = task.Durations[alt];
                        var         name     = $"{task.Name}; Alternative {alt}: {machine.Name}, Duration {duration}";
                        IntervalVar interval = solver.MakeFixedDurationIntervalVar(0, horizon, duration, hasAlternatives, name);
                        alternative.Add(interval);
                        tasksByMachineId[machine.Id].Add(interval);
                        if (hasAlternatives)
                        {
                            activeVariables.Add(interval.PerformedExpr().Var());
                        }
                    }
                    alternative.AlternativeVar = solver.MakeIntVar(0, task.AlternativesCount - 1, task.Name);
                    if (hasAlternatives)
                    {
                        solver.Add(solver.MakeMapDomain(alternative.AlternativeVar, activeVariables));
                    }
                }
            }


            // ----- Create model -----

            // Create precedences inside jobs
            foreach (var taskAltList in tasksByJobId.Values)
            {
                for (int i = 0; i < taskAltList.Count - 1; i++)
                {
                    TaskAlternative currentTaskAlt = taskAltList[i];
                    TaskAlternative nextTaskAlt    = taskAltList[i + 1];
                    foreach (var alt1 in currentTaskAlt)
                    {
                        foreach (var alt2 in nextTaskAlt)
                        {
                            solver.Add(solver.MakeIntervalVarRelation(
                                           alt2, Solver.STARTS_AFTER_END, alt1));
                        }
                    }
                }
            }

            // Collect alternative variables.
            IntVarVector alternativeVariableVec = new IntVarVector();

            foreach (var taskAltList in tasksByJobId.Values)
            {
                foreach (var taskAlt in taskAltList)
                {
                    if (!taskAlt.AlternativeVar.Bound())
                    {
                        alternativeVariableVec.Add(taskAlt.AlternativeVar);
                    }
                }
            }

            // Add disjunctive constraints on unary resources, and create
            // sequence variables. A sequence variable is a dedicated variable
            // whose job is to sequence interval variables.
            SequenceVarVector allSequences = new SequenceVarVector();

            foreach (var machine in data.MachineList)
            {
                DisjunctiveConstraint disjCt = solver.MakeDisjunctiveConstraint(
                    tasksByMachineId[machine.Id], machine.Name);
                solver.Add(disjCt);
                allSequences.Add(disjCt.SequenceVar());
            }

            // Create array of end_times of jobs
            IntVarVector endsVec = new IntVarVector();

            foreach (var taskAltList in tasksByJobId.Values)
            {
                TaskAlternative lastTaskAlt = taskAltList.Last();
                foreach (var alt in lastTaskAlt)
                {
                    endsVec.Add(alt.SafeEndExpr(-1).Var());
                }
            }

            // Objective: minimize the makespan (maximum end times of all tasks)
            // of the problem.
            IntVar      objectiveVar     = solver.MakeMax(endsVec).Var();
            OptimizeVar objectiveMonitor = solver.MakeMinimize(objectiveVar, 1);


            // ----- Search monitors and decision builder -----

            // This decision builder will assign all alternative variables.
            DecisionBuilder alternativePhase = solver.MakePhase(alternativeVariableVec, Solver.CHOOSE_MIN_SIZE, Solver.ASSIGN_MIN_VALUE);

            // This decision builder will rank all tasks on all machines.
            DecisionBuilder sequencePhase = solver.MakePhase(allSequences, Solver.SEQUENCE_DEFAULT);

            // After the ranking of tasks, the schedule is still loose and any
            // task can be postponed at will. But, because the problem is now a PERT
            // (http://en.wikipedia.org/wiki/Program_Evaluation_and_Review_Technique),
            // we can schedule each task at its earliest start time. This is
            // conveniently done by fixing the objective variable to its
            // minimum value.
            DecisionBuilder objectivePhase = solver.MakePhase(objectiveVar, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

            // The main decision builder (ranks all tasks, then fixes the
            // objective_variable).
            DecisionBuilder mainPhase = solver.Compose(alternativePhase, sequencePhase, objectivePhase);

            // Search log
            const int     kLogFrequency = 1000000;
            SearchMonitor searchLog     = solver.MakeSearchLog(kLogFrequency, objectiveMonitor);

            const long  FLAGS_time_limit_in_ms = 1000 * 60 * 20;
            SearchLimit limit = null;

            if (FLAGS_time_limit_in_ms > 0)
            {
                limit = solver.MakeTimeLimit(FLAGS_time_limit_in_ms);
            }

            SolutionCollector collector = solver.MakeLastSolutionCollector();

            collector.AddObjective(objectiveVar);
            collector.Add(alternativeVariableVec);
            collector.Add(allSequences);

            foreach (var taskVec in tasksByMachineId.Values)
            {
                foreach (var task in taskVec)
                {
                    collector.Add(task.StartExpr().Var());
                }
            }


            // ----- Search -----

            bool solutionFound = solver.Solve(mainPhase, searchLog, objectiveMonitor, limit, collector);

            if (solutionFound)
            {
                // The index of the solution from the collector
                const int  SOLUTION_INDEX = 0;
                Assignment solution       = collector.Solution(SOLUTION_INDEX);

                Console.WriteLine();
                uint machineIdx = 0;
                foreach (var seq in allSequences)
                {
                    machineIdx++;
                    var taskSeq = collector.ForwardSequence(SOLUTION_INDEX, seq);
                    Console.WriteLine($"{seq.Name()}:");
                    Console.WriteLine("  Tasks: " + string.Join(", ", taskSeq));

                    //foreach (var taskIndex in storedSequence)
                    //{
                    //    IntervalVar task = sequence.Interval(taskIndex);
                    //    long startMin = solution.StartMin(task);
                    //    long startMax = solution.StartMax(task);
                    //    if (startMin == startMax)
                    //    {
                    //        Console.WriteLine($"Task {task.Name()} starts at {startMin}.");
                    //    }
                    //    else
                    //    {
                    //        Console.WriteLine($"Task {task.Name()} starts between {startMin} and {startMax}.");
                    //    }
                    //}


                    Console.WriteLine();
                    Console.Write("  Starting times:");
                    foreach (var s in taskSeq)
                    {
                        Console.Write(" " + collector.Value(0, tasksByMachineId[machineIdx][s].StartExpr().Var()).ToString());
                    }
                    Console.WriteLine();
                }
                //var x = tasksByMachineId[1][0].StartExpr().Var();
                //var xValStr = collector.Value(0, x).ToString();
                Console.WriteLine("objective function value = " + solution.ObjectiveValue());  //TEMP
            }

            // Save profile in file
            //solver.ExportProfilingOverview("profile.txt");

            // Done
            solver.EndSearch();
        }
예제 #9
0
    public static void Main(String[] args)
    {
        InitTaskList();
        Solver solver = new Solver("Jobshop");

        // ----- Creates all Intervals and vars -----

        // All tasks
        List <IntervalVar> allTasks = new List <IntervalVar>();
        // Stores all tasks attached interval variables per job.
        List <List <IntervalVar> >
        jobsToTasks = new List <List <IntervalVar> >(jobsCount);
        // machinesToTasks stores the same interval variables as above, but
        // grouped my machines instead of grouped by jobs.
        List <List <IntervalVar> >
        machinesToTasks = new List <List <IntervalVar> >(machinesCount);

        for (int i = 0; i < machinesCount; i++)
        {
            machinesToTasks.Add(new List <IntervalVar>());
        }

        // Creates all individual interval variables.
        foreach (List <Task> job in myJobList)
        {
            jobsToTasks.Add(new List <IntervalVar>());
            foreach (Task task in job)
            {
                IntervalVar oneTask = solver.MakeFixedDurationIntervalVar(
                    0, horizon, task.Duration, false, task.Name);
                jobsToTasks[task.JobId].Add(oneTask);
                allTasks.Add(oneTask);
                machinesToTasks[task.Machine].Add(oneTask);
            }
        }

        // ----- Creates model -----

        // Creates precedences inside jobs.
        foreach (List <IntervalVar> jobToTask in jobsToTasks)
        {
            int tasksCount = jobToTask.Count;
            for (int task_index = 0; task_index < tasksCount - 1; ++task_index)
            {
                IntervalVar t1   = jobToTask[task_index];
                IntervalVar t2   = jobToTask[task_index + 1];
                Constraint  prec =
                    solver.MakeIntervalVarRelation(t2, Solver.STARTS_AFTER_END, t1);
                solver.Add(prec);
            }
        }

        // Adds disjunctive constraints on unary resources, and creates
        // sequence variables. A sequence variable is a dedicated variable
        // whose job is to sequence interval variables.
        SequenceVar[] allSequences = new SequenceVar[machinesCount];
        for (int machineId = 0; machineId < machinesCount; ++machineId)
        {
            string name = "Machine_" + machineId;
            DisjunctiveConstraint ct =
                solver.MakeDisjunctiveConstraint(machinesToTasks[machineId].ToArray(),
                                                 name);
            solver.Add(ct);
            allSequences[machineId] = ct.SequenceVar();
        }
        // Creates array of end_times of jobs.
        IntVar[] allEnds = new IntVar[jobsCount];
        for (int i = 0; i < jobsCount; i++)
        {
            IntervalVar task = jobsToTasks[i].Last();
            allEnds[i] = task.EndExpr().Var();
        }

        // Objective: minimize the makespan (maximum end times of all tasks)
        // of the problem.
        IntVar      objectiveVar     = solver.MakeMax(allEnds).Var();
        OptimizeVar objectiveMonitor = solver.MakeMinimize(objectiveVar, 1);

        // ----- Search monitors and decision builder -----

        // This decision builder will rank all tasks on all machines.
        DecisionBuilder sequencePhase =
            solver.MakePhase(allSequences, Solver.SEQUENCE_DEFAULT);

        // After the ranking of tasks, the schedule is still loose and any
        // task can be postponed at will. But, because the problem is now a PERT
        // (http://en.wikipedia.org/wiki/Program_Evaluation_and_Review_Technique),
        // we can schedule each task at its earliest start time. This iscs
        // conveniently done by fixing the objective variable to its
        // minimum value.
        DecisionBuilder objPhase = solver.MakePhase(
            objectiveVar, Solver.CHOOSE_FIRST_UNBOUND, Solver.ASSIGN_MIN_VALUE);

        // The main decision builder (ranks all tasks, then fixes the
        // objectiveVariable).
        DecisionBuilder mainPhase = solver.Compose(sequencePhase, objPhase);

        // Search log.
        const int     kLogFrequency = 1000000;
        SearchMonitor searchLog     =
            solver.MakeSearchLog(kLogFrequency, objectiveMonitor);

        SearchLimit limit = null;

        if (timeLimitInMs > 0)
        {
            limit = solver.MakeTimeLimit(timeLimitInMs);
        }


        SolutionCollector collector = solver.MakeLastSolutionCollector();

        collector.Add(allSequences);
        collector.Add(allTasks.ToArray());
        // Search.
        bool solutionFound = solver.Solve(mainPhase, searchLog, objectiveMonitor,
                                          limit, collector);

        if (solutionFound)
        {
            //The index of the solution from the collector
            const int  SOLUTION_INDEX = 0;
            Assignment solution       = collector.Solution(SOLUTION_INDEX);
            for (int m = 0; m < machinesCount; ++m)
            {
                Console.WriteLine("Machine " + m + " :");
                SequenceVar seq            = allSequences[m];
                int[]       storedSequence = collector.ForwardSequence(SOLUTION_INDEX, seq);
                foreach (int taskIndex in storedSequence)
                {
                    IntervalVar task     = seq.Interval(taskIndex);
                    long        startMin = solution.StartMin(task);
                    long        startMax = solution.StartMax(task);
                    if (startMin == startMax)
                    {
                        Console.WriteLine("Task " + task.Name() + " starts at " +
                                          startMin + ".");
                    }
                    else
                    {
                        Console.WriteLine("Task " + task.Name() + " starts between " +
                                          startMin + " and " + startMax + ".");
                    }
                }
            }
        }
        else
        {
            Console.WriteLine("No solution found!");
        }
    }