// get solver from array of interval variables
    private static Solver GetSolver(IntervalVar[] vars)
    {
      if (vars == null || vars.Length <= 0)
        throw new ArgumentException("Array <vars> cannot be null or empty");

      return vars[0].solver();
    }
Example #2
0
    static void Main()
    {
        CpModel model   = new CpModel();
        int     horizon = 100;

        // C# code supports constant of affine expressions.
        IntVar      start_var    = model.NewIntVar(0, horizon, "start");
        IntVar      end_var      = model.NewIntVar(0, horizon, "end");
        BoolVar     presence_var = model.NewBoolVar("presence");
        IntervalVar interval     = model.NewOptionalIntervalVar(start_var, 10, end_var + 2, presence_var, "interval");

        Console.WriteLine(interval);

        // If the size is fixed, a simpler version uses the start expression, the size and the
        // literal.
        IntervalVar fixedSizeIntervalVar =
            model.NewOptionalFixedSizeIntervalVar(start_var, 10, presence_var, "fixed_size_interval_var");

        Console.WriteLine(fixedSizeIntervalVar);

        // A fixed interval can be created using the same API.
        IntervalVar fixedInterval = model.NewOptionalFixedSizeIntervalVar(5, 10, presence_var, "fixed_interval");

        Console.WriteLine(fixedInterval);
    }
Example #3
0
 public IntervalVar[] MakeFixedDurationIntervalVarArray(int count, int[] start_min, int[] start_max, int[] duration,
                                                        bool optional, string name)
 {
     IntervalVar[] array = new IntervalVar[count];
     for (int i = 0; i < count; ++i)
     {
         array[i] = MakeFixedDurationIntervalVar(start_min[i], start_max[i], duration[i], optional, name + i);
     }
     return(array);
 }
Example #4
0
 static void Main()
 {
     CpModel model     = new CpModel();
     int     horizon   = 100;
     IntVar  start_var = model.NewIntVar(0, horizon, "start");
     // C# code supports IntVar or integer constants in intervals.
     int         duration = 10;
     IntVar      end_var  = model.NewIntVar(0, horizon, "end");
     IntervalVar interval = model.NewIntervalVar(start_var, duration, end_var, "interval");
 }
Example #5
0
 public IntervalVar[] MakeFixedDurationIntervalVarArray(int count, long start_min, long start_max, long duration,
                                                        bool optional)
 {
     IntervalVar[] array = new IntervalVar[count];
     for (int i = 0; i < count; ++i)
     {
         array[i] = MakeFixedDurationIntervalVar(start_min, start_max, duration, optional, "");
     }
     return(array);
 }
Example #6
0
    static void Main()
    {
        InitTaskList();
        int taskCount = GetTaskCount();

        CpModel model = new CpModel();

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

        int endJobCounter = 0;

        foreach (Job j in myJobList)
        {
            BoolVar[] tmp = new BoolVar[j.AlternativeTasks.Count];
            int       i   = 0;
            foreach (Task t in j.AlternativeTasks)
            {
                long ti = taskIndexes[t.Name];
                taskChoosed[ti] = model.NewBoolVar(t.Name + "_choose");
                tmp[i++]        = taskChoosed[ti];
                IntVar start = model.NewIntVar(0, 10000, t.Name + "_start");
                IntVar end   = model.NewIntVar(0, 10000, t.Name + "_end");
                tasks[ti] = model.NewIntervalVar(start, t.Duration, end, t.Name + "_interval");
                if (j.Successor == null)
                {
                    allEnds[endJobCounter++] = end;
                }
                if (!tasksToEquipment.ContainsKey(t.Equipment))
                {
                    tasksToEquipment[t.Equipment] = new List <IntervalVar>();
                }
                tasksToEquipment[t.Equipment].Add(tasks[ti]);
            }
            model.AddExactlyOne(tmp);
        }

        foreach (KeyValuePair <long, List <IntervalVar> > pair in tasksToEquipment)
        {
            model.AddNoOverlap(pair.Value);
        }

        IntVar makespan = model.NewIntVar(0, 100000, "makespan");

        model.AddMaxEquality(makespan, allEnds);
        model.Minimize(makespan);

        // Create the solver.
        CpSolver solver = new CpSolver();

        // Solve the problem.
        solver.Solve(model);
        Console.WriteLine(solver.ResponseStats());
    }
Example #7
0
    static void Main()
    {
        CpModel model = new CpModel();
        // Three weeks.
        int horizon = 21;

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

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

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

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

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

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

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

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

        if (status == CpSolverStatus.Optimal)
        {
            Console.WriteLine("Optimal Schedule Length: " + solver.ObjectiveValue);
            Console.WriteLine("Task 0 starts at " + solver.Value(start_0));
            Console.WriteLine("Task 1 starts at " + solver.Value(start_1));
            Console.WriteLine("Task 2 starts at " + solver.Value(start_2));
        }
    }
Example #8
0
        public IntervalVar[] MakeFixedDurationIntervalVarArray(IntVar[] starts, long[] durations, string name)
        {
            int count = starts.Length;

            IntervalVar[] array = new IntervalVar[count];
            for (int i = 0; i < count; ++i)
            {
                array[i] = MakeFixedDurationIntervalVar(starts[i], durations[i], name + i);
            }
            return(array);
        }
Example #9
0
        public void TestInterval()
        {
            Console.WriteLine("TestInterval test");
            CpModel     model = new CpModel();
            IntVar      v     = model.NewIntVar(-10, 10, "v");
            IntervalVar i     = model.NewFixedSizeIntervalVar(v, 3, "i");

            Assert.Equal("v", i.StartExpr().ShortString());
            Assert.Equal("3", i.SizeExpr().ShortString());
            Assert.Equal("(v + 3)", i.EndExpr().ShortString());
        }
Example #10
0
 static void OptionalIntervalSample()
 {
     CpModel model     = new CpModel();
     int     horizon   = 100;
     IntVar  start_var = model.NewIntVar(0, horizon, "start");
     // C# code supports IntVar or integer constants in intervals.
     int         duration     = 10;
     IntVar      end_var      = model.NewIntVar(0, horizon, "end");
     IntVar      presence_var = model.NewBoolVar("presence");
     IntervalVar interval     = model.NewOptionalIntervalVar(
         start_var, duration, end_var, presence_var, "interval");
 }
Example #11
0
 public Task(IntVar s, IntVar e, IntervalVar i, int oper, List <string> lots, string ent, string recipe, int paket, int prio, int maxOperAgo, int duration)
 {
     start           = s;
     end             = e;
     interval        = i;
     operation       = oper;
     this.lots       = lots;
     entity          = ent;
     this.recipe     = recipe;
     this.paket      = paket;
     priority        = prio;
     sortPriority    = 0;
     this.maxOperAgo = maxOperAgo;
     this.duration   = duration;
 }
Example #12
0
        public static void JobShopCp(List <Job> jobs, int machines)
        {
            CpModel model    = new CpModel();
            int     maxValue = 0;

            foreach (var job in jobs)
            {
                maxValue += job.Tasks.Sum(j => j.Duration);
            }

            List <List <IntervalVar> > intervals         = new List <List <IntervalVar> >(jobs.Count);
            List <List <IntVar> >      starts            = new List <List <IntVar> >(jobs.Count);
            List <List <IntVar> >      ends              = new List <List <IntVar> >(jobs.Count);
            List <List <IntervalVar> > machinesIntervals = new List <List <IntervalVar> >();
            List <List <IntVar> >      machinesStarts    = new List <List <IntVar> >();

            for (int i = 0; i < machines; i++)
            {
                machinesIntervals.Add(new List <IntervalVar>());
                machinesStarts.Add(new List <IntVar>());
            }

            foreach (var job in jobs)
            {
                starts.Add(new List <IntVar>());
                ends.Add(new List <IntVar>());
                intervals.Add(new List <IntervalVar>());
                foreach (var task in job.Tasks)
                {
                    IntVar      start   = model.NewIntVar(0, maxValue, job.Name + task.Name);
                    IntVar      end     = model.NewIntVar(0, maxValue, job.Name + task.Name);
                    IntervalVar oneTask =
                        model.NewIntervalVar(start, task.Duration, end, job.Name + task.Name);
                    intervals[job.JobId].Add(oneTask);
                    starts[job.JobId].Add(start);
                    ends[job.JobId].Add(end);
                    machinesIntervals[task.Machine].Add(oneTask);
                    machinesStarts[task.Machine].Add(start);
                }
            }

            for (int j = 0; j < jobs.Count; ++j)
            {
                for (int t = 0; t < jobs[j].Tasks.Count - 1; ++t)
                {
                    model.Add(ends[j][t] <= starts[j][t + 1]);
                }
            }

            for (int machineId = 0; machineId < machines; ++machineId)
            {
                model.AddNoOverlap(machinesIntervals[machineId].ToArray());
            }

            IntVar[] allEnds = new IntVar[jobs.Count];
            for (int i = 0; i < jobs.Count; i++)
            {
                allEnds[i] = ends[i].Last();
            }

            IntVar makespan = model.NewIntVar(0, maxValue, "makespan");

            model.AddMaxEquality(makespan, allEnds);
            model.Minimize(makespan);

            CpSolver solver = new CpSolver();

            solver.StringParameters = "max_time_in_seconds:30.0";
            CpSolverStatus solverStatus = solver.Solve(model);

            if (solverStatus != CpSolverStatus.Optimal)
            {
                Console.WriteLine("Solver didn’t find optimal solution!");
            }
            Console.WriteLine("Objective value = " + solver.Value(makespan));
        }
Example #13
0
 public IntervalVar[] MakeFixedDurationIntervalVarArray(int count,
                                                        int[] start_min,
                                                        int[] start_max,
                                                        int[] duration,
                                                        bool optional,
                                                        string name) {
   IntervalVar[] array = new IntervalVar[count];
   for (int i = 0; i < count; ++i) {
     array[i] = MakeFixedDurationIntervalVar(start_min[i],
                                             start_max[i],
                                             duration[i],
                                             optional,
                                             name + i);
   }
   return array;
 }
    static void Main()
    {
        CpModel model = new CpModel();
        // Three weeks.
        int horizon   = 100;
        int num_tasks = 4;

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

        IntVar true_var = model.NewConstant(1);

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

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

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

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

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

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

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

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

        if (status == CpSolverStatus.Optimal)
        {
            Console.WriteLine(String.Format("Optimal cost: {0}",
                                            solver.ObjectiveValue));
            Console.WriteLine(String.Format("Makespan: {0}", solver.Value(makespan)));
            for (int t = 0; t < num_tasks; ++t)
            {
                if (solver.BooleanValue(presences[t]))
                {
                    Console.WriteLine(String.Format(
                                          "Task {0} starts at {1} with rank {2}",
                                          t, solver.Value(starts[t]), solver.Value(ranks[t])));
                }
                else
                {
                    Console.WriteLine(String.Format(
                                          "Task {0} in not performed and ranked at {1}", t,
                                          solver.Value(ranks[t])));
                }
            }
        }
        else
        {
            Console.WriteLine(
                String.Format("Solver exited with nonoptimal status: {0}", status));
        }
    }
Example #15
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 #16
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 #17
0
        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);
        }
Example #18
0
    static void Main()
    {
        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);

        Console.WriteLine(model.ModelStats());

        // Creates the solver and solve.
        CpSolver solver = new CpSolver();

        // Display a few solutions picked at random.
        solver.Solve(model);

        // Statistics.
        Console.WriteLine(solver.ResponseStats());
    }
Example #19
0
    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!");
        }
    }
Example #20
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!");
        }
    }
Example #21
0
        public EntityHistory[] GetSolvedTasks(LotInfoJSON[] data, string startDate, int addMinutes)
        {
            List <string> diffList = new List <string>()
            {
                "LPN01", "LPN02", "LPN04", "LPP02", "LPP05", "FHT01", "LPT01", "FOX01", "FOX04", "FAL01"
            };

            Funcs funcs = new Funcs();
            var   date  = funcs.StrToDate(startDate);

            //если передано addMinutes == 25 часов то имеется в виду текущее время
            if (addMinutes == 25 * 60)
            {
                addMinutes = 0;
                date       = DateTime.Now;
            }


            //Горизонт событий
            int horizon = 48 * 60 * 100000;

            // Creates the model.
            CpModel model = new CpModel();


            // Creates jobs.
            List <Task> all_tasks = new List <Task>();

            //Формирование задач для Солвера
            foreach (string ent in diffList)
            {
                //Задачи одной установки
                List <LotTask> entityTasks = new List <LotTask>();
                foreach (var lot in data)
                {
                    foreach (var task in lot.Tasks)
                    {
                        if (task.Entity == ent)
                        {
                            entityTasks.Add(task);
                        }
                    }
                }

                //Удаляем повторения задач
                entityTasks = entityTasks.Distinct(new DistinctItemComparer()).ToList();

                // Добавляем/дополняем задачи для Солвера
                foreach (LotTask t in entityTasks)
                {
                    IntVar      start_var    = model.NewIntVar(t.Delay, horizon, "Task Start");
                    int         duration     = t.Duration;
                    IntVar      end_var      = model.NewIntVar(0, horizon, "Task End");
                    IntervalVar interval_var = model.NewIntervalVar(
                        start_var, duration, end_var,
                        String.Join(' ', getLotsFromPaket(data, t.paket)));
                    //String.Format(getLotsFromPaket(data, t.paket) + t.Operation.ToString() + " " + t.Recipe + " " + t.Duration.ToString() + " " + t.Delay));
                    all_tasks.Add(new Task(start_var, end_var, interval_var, t.Operation, getLotsFromPaket(data, t.paket),
                                           t.Entity, t.Recipe, t.paket, getPriority(data, t.Lot), getMaxOperAgo(data, t.Lot), t.Duration));
                }
            }



            #region Constraints (ограничения, МВХ и условия)

            /*
             * // Последовательность запуска задач (согласно № операции) для одной партии
             * // НЕ ВСЕГДА ВЕРНО!!!
             * foreach(var lot in data.Select(x => x.Lot).ToList())
             * {
             *  var tasks = all_tasks.Where(t => t.lots[0] == lot).ToList().OrderBy(t => t.operation).ToList();
             *
             *  for (int t = 1; t < tasks.Count; t++)
             *      model.Add(tasks[t].start >= tasks[t - 1].end);
             *
             * }*/

            //Назначение приоритетов сортировки по OperAgo & priority
            foreach (var ent in diffList)
            {
                var allEntTasks = all_tasks.Where(e => e.entity == ent).ToList();
                if (allEntTasks.Count > 1)
                {
                    foreach (Task task in allEntTasks)
                    {
                        task.sortPriority = -task.maxOperAgo * 2 + task.priority * 3;          // формула расчёта баллов приоритета
                    }
                    allEntTasks = allEntTasks.OrderByDescending(x => x.sortPriority).ToList(); // чем больше приоритет тем раньше старт

                    for (var t0 = 0; t0 < allEntTasks.Count - 1; t0++)
                    {
                        model.Add(allEntTasks[t0].start < allEntTasks[t0 + 1].start);
                    }
                }
            }

            //МВХ захардкожено
            foreach (var lot in data.Select(x => x.Lot).ToList())
            {
                var tasks = all_tasks.Where(t => t.lots[0] == lot).ToList().OrderBy(t => t.operation).ToList();
                var mbx   = 14;
                for (int t = 1; t < tasks.Count; t++)
                {
                    if (tasks[t].operation == 1015)
                    {
                        mbx = 14;
                    }
                    if (tasks[t].operation == 1120)
                    {
                        mbx = 14;
                    }
                    if (tasks[t].operation == 1350)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 1380)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 1390)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 2280)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 2292)
                    {
                        mbx = 14;
                    }
                    if (tasks[t].operation == 2390)
                    {
                        mbx = 14;
                    }
                    if (tasks[t].operation == 2410)
                    {
                        mbx = 8;
                    }
                    if (tasks[t].operation == 3270)
                    {
                        mbx = 14;
                    }
                    if (tasks[t].operation == 3280)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 3390)
                    {
                        mbx = 14;
                    }
                    if (tasks[t].operation == 3410)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 4520)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 4560)
                    {
                        mbx = 72;
                    }
                    if (tasks[t].operation == 4960)
                    {
                        mbx = 24;
                    }
                    if (tasks[t].operation == 4990)
                    {
                        mbx = 72;
                    }
                    model.Add(tasks[t].start - tasks[t - 1].end <= mbx); //  МВХ 14 часов
                }
            }

            //Ограничение на продувки для FOX01
            //Продувки после процесса:  После каждого процесса OXIDE16T, OXIDE58TM, OXIDE581TM, OX533TM,
            //        OX531TM, OXIDE70TM, OXPO01C (АЛЬТЕРНАТИВНЫЙ) продувка WET-DCE-CLN - 280 мин
            var           FOX01Tasks    = all_tasks.Where(t => t.entity == "FOX01").ToList();
            List <string> FOX01Recipies = new List <string>()
            {
                "OXIDE16T", "OXIDE58TM", "OXIDE581TM", "OX533TM", "OX531TM", "OXIDE70TM", "OXPO01C"
            };
            for (int t = 0; t < FOX01Tasks.Count; t++)
            {
                if (FOX01Recipies.Contains(FOX01Tasks[t].recipe))
                {
                    IntVar      start_var    = model.NewIntVar(0, horizon, "Purge Start");
                    int         duration     = 280;
                    IntVar      end_var      = model.NewIntVar(0, horizon, "Purge End");
                    IntervalVar interval_var = model.NewIntervalVar(start_var, duration, end_var, "After " + FOX01Tasks[t].recipe + " WET-DCE-CLN 280 min");

                    var purgeTask = new Task(start_var, end_var, interval_var, 0, new List <string>()
                    {
                        "FOX01 Purge"
                    }, "FOX01", "WET-DCE-CLN", 0, -1, 0, 280);
                    all_tasks.Add(purgeTask);

                    //model.Add(purgeTask.start >= FOX01Tasks[t].end);
                    model.Add(purgeTask.start - FOX01Tasks[t].end < 10);
                    model.Add(purgeTask.start - FOX01Tasks[t].end > 0);
                }
                ;
            }

            //Ограничение на продувки для LPN02
            // До и после  обработки NIT1100A, NIT1500A, NITR1500K, NITR01 должна проходить
            //    ОБЯЗАТЕЛЬНО необходимая технологическая продувка 20-CYCLE-PURGE = 200 мин

            var           LPN02Tasks    = all_tasks.Where(t => t.entity == "LPN02").ToList();
            List <string> LPN02Recipies = new List <string>()
            {
                "NIT1100A", "NIT1500A", "NITR1500K", "NITR01"
            };

            //ограничение на продувку после рецепта
            for (int t = 0; t < LPN02Tasks.Count; t++)
            {
                if (LPN02Recipies.Contains(LPN02Tasks[t].recipe))
                {
                    IntVar      start_var    = model.NewIntVar(0, horizon, "Purge Start");
                    IntVar      end_var      = model.NewIntVar(0, horizon, "Purge End");
                    IntervalVar interval_var = model.NewIntervalVar(start_var, 200, end_var, "After " + LPN02Tasks[t].recipe + " 20-CYCLE-PURGE 200 min");

                    var purgeTaskAfter = new Task(start_var, end_var, interval_var, 0, new List <string> {
                        "Purge After"
                    }, "LPN02", "20-CYCLE-PURGE", 0, -1, 0, 200);
                    all_tasks.Add(purgeTaskAfter);
                    model.Add(purgeTaskAfter.start - LPN02Tasks[t].end < 10);
                    model.Add(purgeTaskAfter.start - LPN02Tasks[t].end > 0);
                }
                ;
            }

            //ограничение на продувку до рецепта
            for (int t = 0; t < LPN02Tasks.Count; t++)
            {
                if (LPN02Recipies.Contains(LPN02Tasks[t].recipe))
                {
                    IntVar      start_var    = model.NewIntVar(0, horizon, "Purge Start");
                    IntVar      end_var      = model.NewIntVar(0, horizon, "Purge End");
                    IntervalVar interval_var = model.NewIntervalVar(start_var, 200, end_var, "Before " + LPN02Tasks[t].recipe + " 20-CYCLE-PURGE 200 min");

                    var purgeTaskBefore = new Task(start_var, end_var, interval_var, 0, new List <string> {
                        "Purge Before"
                    }, "LPN02", "20-CYCLE-PURGE", 0, -1, 0, 200);
                    all_tasks.Add(purgeTaskBefore);
                    model.Add(LPN02Tasks[t].start - purgeTaskBefore.end < 10);
                    model.Add(LPN02Tasks[t].start - purgeTaskBefore.end > 0);
                }
                ;
            }

            //!!!НУЖНО СДЕЛАТЬ!!! Ограничение: запрет 2-х продувок подряд !!!НУЖНО СДЕЛАТЬ!!!
            //var tasksBefore = all_tasks.Where(b => b.lot == "Purge Before").ToList();
            //var tasksAfter = all_tasks.Where(a => a.lot == "Purge After").ToList();


            // Ограничение на отсутствие пересечений задач для одной установки
            foreach (var ent in diffList)
            {
                List <IntervalVar> machine_to_jobs = new List <IntervalVar>();
                var entTasks = all_tasks.Where(t => (t.entity == ent)).ToList();

                for (int j = 0; j < entTasks.Count; j++)
                {
                    machine_to_jobs.Add(entTasks[j].interval);
                }

                model.AddNoOverlap(machine_to_jobs);
            }

            var test = all_tasks.Where(t => t.recipe == "MSHTO05").ToList();

            // Makespan objective.
            IntVar[] all_ends = new IntVar[all_tasks.Count];
            for (int j = 0; j < all_tasks.Count; j++)
            {
                all_ends[j] = all_tasks[j].end;
            }

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

            model.AddMaxEquality(makespan, all_ends);
            model.Minimize(makespan);

            #endregion

            // Creates the solver and solve.
            CpSolver solver = new CpSolver();

            //максимальное время расчёта
            solver.StringParameters = "max_time_in_seconds:" + "40";

            solver.Solve(model);

            #region Преобразование в EntityHistory[] для Gantt chart

            List <EntityHistory> solvedEntityHistories = new List <EntityHistory>();
            DateTime             firstDate             = new DateTime(1970, 1, 1, 0, 0, 0);
            long startTime = (long)(date.AddMinutes(addMinutes) - firstDate).TotalSeconds;
            int  id        = 0;
            foreach (var ent in diffList)
            {
                var tempEntityHistory = new EntityHistory();
                tempEntityHistory.Id     = id;
                tempEntityHistory.Parent = ent;
                tempEntityHistory.Name   = ent + "_план";
                var entAllTasks = all_tasks.Where(t => t.entity == ent).ToList();
                foreach (Task task in entAllTasks)
                {
                    LotInfoPeriodGantt per = new LotInfoPeriodGantt();
                    per.color         = getColor(task.priority);
                    per.start         = (startTime + solver.Value(task.start) * 60) * 1000 + 120000;
                    per.end           = (startTime + solver.Value(task.end) * 60) * 1000 - 120000;
                    per.duration      = task.duration;
                    per.id            = id;
                    per.lot           = task.interval.Name();
                    per.operation     = task.operation.ToString();
                    per.recipe        = task.recipe;
                    per.connectTo     = "";
                    per.connectorType = "finish - start";
                    tempEntityHistory.Periods.Add(per);
                    id++;
                }

                solvedEntityHistories.Add(tempEntityHistory);
            }
            #endregion

            return(solvedEntityHistories.ToArray());
        }
Example #22
0
        public static void WiTiCp(List <TaskWiti> tasks)
        {
            var model = new CpModel();
            //int variablesMaxValue = 0;
            int timeSum = tasks.Sum(x => x.P);

            //foreach (var task in tasks)
            //    variablesMaxValue += ((timeSum - task.D) > 0 ? (timeSum - task.D) : 0) * task.W;

            IntVar[]      starts     = new IntVar[tasks.Count];
            IntVar[]      ends       = new IntVar[tasks.Count];
            IntVar[]      punishment = new IntVar[tasks.Count];
            IntervalVar[] intervals  = new IntervalVar[tasks.Count];
            //var witi = model.NewIntVar(0, variablesMaxValue, "witi");

            for (int i = 0; i < tasks.Count; i++)
            {
                starts[i] = model.NewIntVar(0, timeSum, $"start_task{i}");
            }
            for (int i = 0; i < tasks.Count; i++)
            {
                ends[i]      = model.NewIntVar(0, timeSum, $"end_task{i}");
                intervals[i] = model.NewIntervalVar(starts[i], tasks[i].P, ends[i], $"interval{i}");
            }
            for (int i = 0; i < tasks.Count; i++)
            {
                if ((timeSum - tasks[i].D) > 0)
                {
                    punishment[i] = model.NewIntVar(0, (timeSum - tasks[i].D) * tasks[i].W, $"punish_task{i}");
                }
                else
                {
                    punishment[i] = model.NewIntVar(0, 0, $"punish_task{i}");
                }
            }

            model.AddNoOverlap(intervals);

            /*
             * foreach (var task in tasks)
             * {
             * model.Add(ends[tasks.IndexOf(task)] == starts[tasks.IndexOf(task)] + task.P);
             * }
             * foreach (var task in tasks)
             * {
             * model.Add(witi >= (ends[tasks.IndexOf(task)] - task.D) * task.W);
             * }*/
            foreach (var task in tasks)
            {
                model.Add(punishment[tasks.IndexOf(task)] >= (ends[tasks.IndexOf(task)] - task.D) * task.W);
            }
            //foreach (var task in tasks)
            //{
            //    model.Add(punishment[tasks.IndexOf(task)] <= ((timeSum - task.D) > 0 ? (timeSum - task.D) : 0) * task.W);
            //}


            var witi = punishment.Sum();

            model.Minimize(witi);

            CpSolver solver = new CpSolver();

            solver.StringParameters = "max_time_in_seconds:30.0";
            CpSolverStatus solverStatus = solver.Solve(model);

            if (solverStatus != CpSolverStatus.Optimal)
            {
                Console.WriteLine("Solver didn’t find optimal solution!");
            }
            Console.WriteLine("Objective value = " + solver.Value(witi));
        }
Example #23
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.");
            }
        }
Example #24
0
 public IntervalVar[] MakeFixedDurationIntervalVarArray(int count,
                                                        long start_min,
                                                        long start_max,
                                                        long duration,
                                                        bool optional) {
   IntervalVar[] array = new IntervalVar[count];
   for (int i = 0; i < count; ++i) {
     array[i] = MakeFixedDurationIntervalVar(start_min,
                                             start_max,
                                             duration,
                                             optional,
                                             "");
   }
   return array;
 }
Example #25
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;
            SearchMonitor search_log =
            solver.MakeSearchLog(kLogFrequency, objective_monitor);

            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.");
        }
Example #26
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();
        }
Example #27
0
 public Task(IntVar s, IntVar e, IntervalVar i)
 {
     start    = s;
     end      = e;
     interval = i;
 }
Example #28
0
    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!");
        }
    }
Example #29
0
    public static void Main(String[] args)
    {
        InitTaskList();
        CpModel model = new CpModel();

        // ----- Creates all intervals and integer variables -----

        // Stores all tasks attached interval variables per job.
        List <List <IntervalVar> > jobsToTasks  = new List <List <IntervalVar> >(jobsCount);
        List <List <IntVar> >      jobsToStarts = new List <List <IntVar> >(jobsCount);
        List <List <IntVar> >      jobsToEnds   = new List <List <IntVar> >(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);
        List <List <IntVar> >      machinesToStarts = new List <List <IntVar> >(machinesCount);

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

        // Creates all individual interval variables.
        foreach (List <Task> job in myJobList)
        {
            jobsToTasks.Add(new List <IntervalVar>());
            jobsToStarts.Add(new List <IntVar>());
            jobsToEnds.Add(new List <IntVar>());
            foreach (Task task in job)
            {
                IntVar      start   = model.NewIntVar(0, horizon, task.Name);
                IntVar      end     = model.NewIntVar(0, horizon, task.Name);
                IntervalVar oneTask = model.NewIntervalVar(start, task.Duration, end, task.Name);
                jobsToTasks[task.JobId].Add(oneTask);
                jobsToStarts[task.JobId].Add(start);
                jobsToEnds[task.JobId].Add(end);
                machinesToTasks[task.Machine].Add(oneTask);
                machinesToStarts[task.Machine].Add(start);
            }
        }

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

        // Creates precedences inside jobs.
        for (int j = 0; j < jobsToTasks.Count; ++j)
        {
            for (int t = 0; t < jobsToTasks[j].Count - 1; ++t)
            {
                model.Add(jobsToEnds[j][t] <= jobsToStarts[j][t + 1]);
            }
        }

        // Adds no_overkap constraints on unary resources.
        for (int machineId = 0; machineId < machinesCount; ++machineId)
        {
            model.AddNoOverlap(machinesToTasks[machineId]);
        }

        // Creates array of end_times of jobs.
        IntVar[] allEnds = new IntVar[jobsCount];
        for (int i = 0; i < jobsCount; i++)
        {
            allEnds[i] = jobsToEnds[i].Last();
        }

        // Objective: minimize the makespan (maximum end times of all tasks)
        // of the problem.
        IntVar makespan = model.NewIntVar(0, horizon, "makespan");

        model.AddMaxEquality(makespan, allEnds);
        model.Minimize(makespan);

        // Create the solver.
        CpSolver solver = new CpSolver();

        // Set the time limit.
        if (timeLimitInSeconds > 0)
        {
            solver.StringParameters = "max_time_in_seconds:" + timeLimitInSeconds;
        }
        // Solve the problem.
        CpSolverStatus status = solver.Solve(model);

        if (status == CpSolverStatus.Optimal)
        {
            Console.WriteLine("Makespan = " + solver.ObjectiveValue);
            for (int m = 0; m < machinesCount; ++m)
            {
                Console.WriteLine($"Machine {m}:");
                SortedDictionary <long, string> starts = new SortedDictionary <long, string>();
                foreach (IntVar var in machinesToStarts[m])
                {
                    starts[solver.Value(var)] = var.Name();
                }
                foreach (KeyValuePair <long, string> p in starts)
                {
                    Console.WriteLine($"  Task {p.Value} starts at {p.Key}");
                }
            }
        }
        else
        {
            Console.WriteLine("No solution found!");
        }
    }
Example #30
0
 public IntervalVar[] MakeFixedDurationIntervalVarArray(IntVar[] starts,
                                                        long[] durations,
                                                        string name) {
   int count = starts.Length;
   IntervalVar[] array = new IntervalVar[count];
   for (int i = 0; i < count; ++i) {
     array[i] = MakeFixedDurationIntervalVar(starts[i],
                                             durations[i],
                                             name + i);
   }
   return array;
 }
    /**
     *
     * Moving furnitures (scheduling) problem in Google CP Solver.
     *
     * Marriott & Stukey: 'Programming with constraints', page  112f
     *
     * Also see http://www.hakank.org/or-tools/furniture_moving.py
     *
     */
    private static void Solve()
    {
        Solver solver = new Solver("FurnitureMovingIntervals");

        const int n = 4;

        int[]     durations       = { 30, 10, 15, 15 };
        int[]     demand          = { 3, 1, 3, 2 };
        const int upper_limit     = 160;
        const int max_num_workers = 5;

        //
        // Decision variables
        //
        IntervalVar[] tasks = new IntervalVar[n];
        for (int i = 0; i < n; ++i)
        {
            tasks[i] =
                solver.MakeFixedDurationIntervalVar(0, upper_limit - durations[i], durations[i], false, "task_" + i);
        }

        // Fillers that span the whole resource and limit the available
        // number of workers.
        IntervalVar[] fillers = new IntervalVar[max_num_workers];
        for (int i = 0; i < max_num_workers; ++i)
        {
            fillers[i] = solver.MakeFixedDurationIntervalVar(0, 0, upper_limit, true, "filler_" + i);
        }

        // Number of needed resources, to be minimized or constrained.
        IntVar num_workers = solver.MakeIntVar(0, max_num_workers, "num_workers");

        // Links fillers and num_workers.
        for (int i = 0; i < max_num_workers; ++i)
        {
            solver.Add((num_workers > i) + fillers[i].PerformedExpr() == 1);
        }

        // Creates makespan.
        IntVar[] ends = new IntVar[n];
        for (int i = 0; i < n; ++i)
        {
            ends[i] = tasks[i].EndExpr().Var();
        }
        IntVar end_time = ends.Max().VarWithName("end_time");

        //
        // Constraints
        //
        IntervalVar[] all_tasks   = new IntervalVar[n + max_num_workers];
        int[]         all_demands = new int[n + max_num_workers];
        for (int i = 0; i < n; ++i)
        {
            all_tasks[i]   = tasks[i];
            all_demands[i] = demand[i];
        }
        for (int i = 0; i < max_num_workers; ++i)
        {
            all_tasks[i + n]   = fillers[i];
            all_demands[i + n] = 1;
        }
        solver.Add(all_tasks.Cumulative(all_demands, max_num_workers, "workers"));

        //
        // Some extra constraints to play with
        //

        // all tasks must end within an hour
        // solver.Add(end_time <= 60);

        // All tasks should start at time 0
        // for(int i = 0; i < n; i++) {
        //   solver.Add(tasks[i].StartAt(0));
        // }

        // limitation of the number of people
        // solver.Add(num_workers <= 3);
        solver.Add(num_workers <= 4);

        //
        // Objective
        //

        // OptimizeVar obj = num_workers.Minimize(1);
        OptimizeVar obj = end_time.Minimize(1);

        //
        // Search
        //
        DecisionBuilder db = solver.MakePhase(all_tasks, Solver.INTERVAL_DEFAULT);

        solver.NewSearch(db, obj);

        while (solver.NextSolution())
        {
            Console.WriteLine(num_workers.ToString() + ", " + end_time.ToString());
            for (int i = 0; i < n; i++)
            {
                Console.WriteLine("{0} (demand:{1})", tasks[i].ToString(), demand[i]);
            }
            Console.WriteLine();
        }

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

        solver.EndSearch();
    }
  /**
   *
   * Moving furnitures (scheduling) problem in Google CP Solver.
   *
   * Marriott & Stukey: 'Programming with constraints', page  112f
   *
   * Also see http://www.hakank.org/or-tools/furniture_moving.py
   *
   */
  private static void Solve()
  {
    Solver solver = new Solver("FurnitureMovingIntervals");

    const int n = 4;
    int[] durations = {30,10,15,15};
    int[] demand = {3, 1, 3, 2};
    const int upper_limit = 160;
    const int max_num_workers = 5;

    //
    // Decision variables
    //
    IntervalVar[] tasks = new IntervalVar[n];
    for (int i = 0; i < n; ++i)
    {
      tasks[i] = solver.MakeFixedDurationIntervalVar(0,
                                                     upper_limit - durations[i],
                                                     durations[i],
                                                     false,
                                                     "task_" + i);
    }

    // Fillers that span the whole resource and limit the available
    // number of workers.
    IntervalVar[] fillers = new IntervalVar[max_num_workers];
    for (int i = 0; i < max_num_workers; ++i)
    {
      fillers[i] = solver.MakeFixedDurationIntervalVar(0,
                                                       0,
                                                       upper_limit,
                                                       true,
                                                       "filler_" + i);
    }

    // Number of needed resources, to be minimized or constrained.
    IntVar num_workers  = solver.MakeIntVar(0, max_num_workers, "num_workers");
    // Links fillers and num_workers.
    for (int i = 0; i < max_num_workers; ++i)
    {
      solver.Add((num_workers > i) + fillers[i].PerformedExpr() == 1);
    }

    // Creates makespan.
    IntVar[] ends = new IntVar[n];
    for (int i = 0; i < n; ++i)
    {
      ends[i] = tasks[i].EndExpr().Var();
    }
    IntVar end_time = ends.Max().VarWithName("end_time");

    //
    // Constraints
    //
    IntervalVar[] all_tasks = new IntervalVar[n + max_num_workers];
    int[] all_demands = new int[n + max_num_workers];
    for (int i = 0; i < n; ++i)
    {
      all_tasks[i] = tasks[i];
      all_demands[i] = demand[i];
    }
    for (int i = 0; i < max_num_workers; ++i)
    {
      all_tasks[i + n] = fillers[i];
      all_demands[i + n] = 1;
    }
    solver.Add(all_tasks.Cumulative(all_demands, max_num_workers, "workers"));

    //
    // Some extra constraints to play with
    //

    // all tasks must end within an hour
    // solver.Add(end_time <= 60);

    // All tasks should start at time 0
    // for(int i = 0; i < n; i++) {
    //   solver.Add(tasks[i].StartAt(0));
    // }


    // limitation of the number of people
    // solver.Add(num_workers <= 3);
    solver.Add(num_workers <= 4);

    //
    // Objective
    //

    // OptimizeVar obj = num_workers.Minimize(1);
    OptimizeVar obj = end_time.Minimize(1);

    //
    // Search
    //
    DecisionBuilder db = solver.MakePhase(all_tasks, Solver.INTERVAL_DEFAULT);

    solver.NewSearch(db, obj);

    while (solver.NextSolution()) {
      Console.WriteLine(num_workers.ToString() + ", " + end_time.ToString());
      for(int i = 0; i < n; i++) {
        Console.WriteLine("{0} (demand:{1})", tasks[i].ToString(), demand[i]);
      }
      Console.WriteLine();
    }

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

    solver.EndSearch();

  }