Esempio n. 1
0
        /// <summary>
        /// Assign the shifts as is from the constrains
        /// Can cause conflicts in schedulare
        /// </summary>
        /// <param name="schedulare"></param>
        /// <param name="shiftsContainer"></param>
        private static void InitialTheSchedular(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            foreach (var emp in shiftsContainer.EmployeeConstraints)
            {
                var currEmpName = new Worker()
                {
                    Name = emp.Name
                };

                foreach (var empDayConstraint in emp.WeeklyConstraints)
                {
                    if (empDayConstraint.Value.Contains("Free day"))
                    {
                        continue;
                    }

                    var constraintsDay   = empDayConstraint.Key;
                    var constraintsShift = empDayConstraint.Value;

                    var schedulareDay = schedulare.Days.FirstOrDefault(x => x.Name.Contains(constraintsDay));

                    var schedulareShift = schedulareDay.Shifts.FirstOrDefault(x => x.Name.Contains(constraintsShift));

                    schedulareShift.Workers.Add(currEmpName);
                }
            }
        }
Esempio n. 2
0
        protected SchedulareState GetSchedulareState(Schedulare schedulare, ShiftsContainer shiftsContainer, TreeNode <Schedulare> treeNode = null)
        {
            var weight = 0;

            // if workers have 2 shifts in the row +10
            TwoShiftsInARowWeight(schedulare, shiftsContainer, ref weight);

            // if worker did not got the shift he asked for +20
            LackSatisfactionConstraintsWeight(schedulare, shiftsContainer, ref weight);

            // if worker have 5 work days in the row +20
            var shiftsInARow = 3;

            ShiftsInARow(schedulare, shiftsContainer, ref weight, shiftsInARow);

            // if worker got shift that he did not asked +20
            UnwantedShift(schedulare, shiftsContainer, ref weight);

            // if worker assinghned twice on the same shift
            TwiceOnTheSameShift(schedulare, shiftsContainer, ref weight);

            return(new SchedulareState()
            {
                Node = treeNode, Weight = weight
            });
        }
Esempio n. 3
0
        private void ValidateInitialStep(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            var validNumberOfWorkersInShift = shiftsContainer.ShiftParams.NumberOfWokersInShift;

            foreach (var day in schedulare.Days)
            {
                foreach (var shift in day.Shifts)
                {
                    if (validNumberOfWorkersInShift >= shift.Workers.Count())
                    {
                        continue;
                    }

                    var randList = GetListOfRandomNumber(shift.Workers.Count());

                    List <int> fortuneWorkerIndexList = GetFortuneWorkerIndexList(validNumberOfWorkersInShift, randList);

                    List <Worker> fortuneWorkerList = InitializeFortuneWorkers(shift, fortuneWorkerIndexList);

                    var names = fortuneWorkerList.Select(x => x.Name).ToList();
                    var workersThatWereRemoved = shift.Workers.Where(x => !names.Any(y => y.CompareContent(x.Name))).ToList();

                    //add workers what was not lucky to the back log
                    _workersBackLog.AddRange(workersThatWereRemoved);

                    shift.Workers = fortuneWorkerList;
                }
            }
        }
Esempio n. 4
0
        public override SchedulareState Execute(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            _schedulare      = schedulare;
            _shiftsContainer = shiftsContainer;

            _executeStopwatch.Start();

            _workersBackLog   = new List <Worker>();
            _unresolvedShifts = new List <Day>();

            // step 1 init with all the constrains
            InitialTheSchedular(schedulare, shiftsContainer);

            // step 2 validate shifts
            ValidateInitialStep(schedulare, shiftsContainer);

            // step 3 resolve conflicts from previous step
            ResolveAndFillTheSchdulare(schedulare, shiftsContainer);

            var executionTime = _executeStopwatch.Elapsed.TotalSeconds;

            _executeStopwatch.Reset();

            var schedulareState = GetSchedulareState(schedulare, shiftsContainer, new TreeNode <Schedulare>(schedulare));

            schedulareState.ExecuteTime = executionTime;

            return(schedulareState);
        }
Esempio n. 5
0
        private SchedulareState RunRandAlgo(ShiftsContainer shiftsContainer, Schedulare schedulare)
        {
            var randAlgo   = _factory.GetAlgo("Rand");
            var randResult = randAlgo.Execute(schedulare.DeepClone(), shiftsContainer);

            PrintDebugData(shiftsContainer, randResult, randAlgo.ToString());
            UpdateSchefulareStatistics(shiftsContainer, randResult, randAlgo.ToString());
            return(randResult);
        }
Esempio n. 6
0
        private void InitParams(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            ShiftsContainer = shiftsContainer;

            OpenSet = new SortedArray <SchedulareState>(new SchedulareComparerArray());

            TreeRoot = new TreeNode <Schedulare>(schedulare);

            CloseSet = new SortedArray <SchedulareState>(new SchedulareComparerArray());
        }
Esempio n. 7
0
        private void InitParams(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            ShiftsContainer = shiftsContainer;

            CloseSet = new IntervalHeap <SchedulareState>(new SchedulareComparer());

            OpenSet = new IntervalHeap <SchedulareState>(new SchedulareComparer());

            TreeRoot = new TreeNode <Schedulare>(schedulare);
        }
Esempio n. 8
0
        private void InitParams(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            ShiftsContainer = shiftsContainer;

            TreeRoot = new TreeNode <Schedulare>(schedulare);

            CloseSet = new CircularList(20);

            OpenSet = new IntervalHeap <SchedulareState>(new SchedulareComparer());

            ExplorationStopwatch = new Stopwatch();
        }
Esempio n. 9
0
        private void RunHuristicMethods()
        {
            var shiftsContainer = _constructsShift.Excute();

            var schedulare = new Schedulare(shiftsContainer);

            var randResult = RunRandAlgo(shiftsContainer, schedulare);

            foreach (var algo in _factory.GetAll())
            {
                RunAlgo(shiftsContainer, schedulare, randResult, algo);
            }
        }
Esempio n. 10
0
        private void AssignRandomEmployee(Schedulare schedulare, Day schedulareDay, Shift schedulareShift)
        {
            Func <Schedulare, Day, Shift, bool, bool> action = TryOrAssignEmployee;
            var isAssined = CommonLogic.TryWithRetries(20, () => TryOrAssignEmployee(schedulare, schedulareDay, schedulareShift));

            if (!isAssined) // failed to fill current shift 'schedulareShift'
            {
                TryOrAssignEmployee(schedulare, schedulareDay, schedulareShift, false);
                _unresolvedShifts.Add(new Day()
                {
                    Name = schedulareDay.Name, Shifts = schedulareDay.Shifts.Where(x => x.Name.CompareContent(schedulareShift.Name)).ToList()
                });
            }
        }
Esempio n. 11
0
        private List <DayShift> GetShiftList(Schedulare value)
        {
            var shiftsList = value.Days.SelectMany(x => x.Shifts).ToList();

            var list = new List <DayShift>();

            foreach (var day in value.Days)
            {
                foreach (var shift in day.Shifts)
                {
                    list.Add(new DayShift()
                    {
                        DayName = day.Name, Shift = shift
                    });
                }
            }

            return(list);
        }
Esempio n. 12
0
        protected int UnwantedShift(Schedulare schedulare, ShiftsContainer shiftsContainer, ref int weight)
        {
            try
            {
                foreach (var employee in shiftsContainer.EmployeeConstraints)
                {
                    var currEmpConstraints = employee.WeeklyConstraints.Where(x => !x.Value.ContainsContent("Free day")).ToList();

                    foreach (var day in schedulare.Days)
                    {
                        foreach (var shift in day.Shifts)
                        {
                            if (!shift.Workers.Any(x => x.Name.CompareContent(employee.Name)))
                            {
                                continue;
                            }

                            var constraintDay = currEmpConstraints.FirstOrDefault(x => x.Key.CompareContent(day.Name));

                            if (constraintDay.Key == null)
                            {
                                continue;
                            }

                            // if the employee asked for this shift skip
                            if (constraintDay.Value.CompareContent(shift.Name))
                            {
                                continue;
                            }

                            weight += _unwantedShift;
                        }
                    }
                }

                return(weight);
            }
            catch (Exception e)
            {
                CommonLogic.ApeandToFile(e.ToString());
            }
            return(default);
Esempio n. 13
0
        private bool TryOrAssignEmployee(Schedulare schedulare, Day schedulareDay, Shift schedulareShift, bool validate = true)
        {
            var randomEmployee = GetRandomEmployee();

            if (validate) // validate if the employee can enter the shift
            {
                if (!CommonLogic.IsValidToAssign(schedulare, schedulareDay, schedulareShift, randomEmployee))
                {
                    return(false);
                }
            }

            // add worker to the schedulare
            schedulareShift.Workers.Add(randomEmployee);

            // remove worker from the backlog
            _workersBackLog.Remove(randomEmployee);

            return(true);
        }
Esempio n. 14
0
        private void RunAlgo(ShiftsContainer shiftsContainer, Schedulare schedulare, SchedulareState randResult, KeyValuePair <string, IAlgo> algo)
        {
            SchedulareState result = null;

            if (algo.Key.ContainsContent("rand"))
            {
                return;
            }

            if (algo.Key.ContainsContent("tabu"))
            {
                result = algo.Value.Execute(randResult.Node.Value.DeepClone(), shiftsContainer);
            }
            else
            {
                result = algo.Value.Execute(schedulare.DeepClone(), shiftsContainer);
            }

            PrintDebugData(shiftsContainer, result, algo.Key.ToString());
            UpdateSchefulareStatistics(shiftsContainer, result, algo.Key.ToString());
        }
Esempio n. 15
0
        private void ResolveAndFillTheSchdulare(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            var numberOfWokersInShift = shiftsContainer.ShiftParams.NumberOfWokersInShift;

            while (!_workersBackLog.Count.Equals(0))
            {
                // get available shifts
                var days = schedulare.Days.DeepClone();
                var tempAvailableShifts = days.Select(x => new { x.Name, Shifts = x.Shifts.Where(y => y.Workers.Count < numberOfWokersInShift).ToList() }).ToList();
                var availableShifts     = tempAvailableShifts.Where(x => !x.Shifts.IsNullOrEmpty()).ToList();

                // fetch shift from back log
                var backLogShiftDayToFill = availableShifts.FirstOrDefault();
                var backLogShiftToFill    = new { backLogShiftDayToFill.Name, Shift = backLogShiftDayToFill.Shifts.FirstOrDefault() };

                // fetch matching shift from schedulare as was fetched from the backlog
                var schedulareDay   = schedulare.Days.FirstOrDefault(x => x.Name.ContainsContent(backLogShiftDayToFill.Name));
                var schedulareShift = schedulareDay.Shifts.FirstOrDefault(x => x.Name.CompareContent(backLogShiftToFill.Shift.Name));

                AssignRandomEmployee(schedulare, schedulareDay, schedulareShift);
            }
        }
Esempio n. 16
0
        public override SchedulareState Execute(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            this.schedulare      = schedulare;
            this.shiftsContainer = shiftsContainer;
            greedyEmpList        = new List <GreedyEmployee>();

            _executeStopwatch.Start();

            StartAlgorithm();

            var executionTime = _executeStopwatch.Elapsed.TotalSeconds;

            _executeStopwatch.Reset();

            conflicts = new List <GreedyEmployee>();

            var schedulareState = GetSchedulareState(schedulare, shiftsContainer, new TreeNode <Schedulare>(schedulare));

            schedulareState.ExecuteTime = executionTime;

            return(schedulareState);
        }
Esempio n. 17
0
        public override SchedulareState Execute(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            InitParams(schedulare, shiftsContainer);

            var schedulareState = GetSchedulareState(schedulare.DeepClone(), shiftsContainer, TreeRoot);

            UpdateCurrentBestSolution(schedulareState);

            OpenSet.Add(schedulareState);

            ExecuteStopwatch.Start();

            var shiftsList = GetShiftList(schedulareState.Node.Value);

            while (!IsGoal())
            {
                var randShift = GetRandomShift(shiftsList);

                // DEBUG
                PrintDebugData(shiftsContainer, CurrentBestSolution);

                ExplorationStopwatch.Reset();

                ExplorationStopwatch.Start();

                #region Exploration loop

                while (ExplorationStopwatch.Elapsed.TotalSeconds < EXPLORATION_TIME_SECONDS)
                {
                    // IsGoal
                    // OR break id exploration ended with no result
                    if (IsGoal() || OpenSet.Count.Equals(0))
                    {
                        break;
                    }

                    var currState = OpenSet.FindMin();

                    UpdateCurrentBestSolution(currState);

                    OpenSet.DeleteMin();

                    CloseSet.Add(currState.Node.Value);


                    for (int workerIndex = 0; workerIndex < randShift.Shift.Workers.Count; workerIndex++)
                    {
                        var currStateInOrderToReplaceEmp = currState.DeepClone();

                        var currStateNodeInOrderToReplaceEmp = currStateInOrderToReplaceEmp.Node;

                        RemoveEmpFromCurrShift(randShift, workerIndex, currStateInOrderToReplaceEmp);

                        // DEBUG
                        PrintDebugData(shiftsContainer, currStateInOrderToReplaceEmp);

                        #region build new nodes
                        foreach (var emp in shiftsContainer.EmployeeConstraints.Select(x => x.Name))
                        {
                            var newNodeSchedulare = currStateNodeInOrderToReplaceEmp.Value.DeepClone();

                            var currShiftToAssin = GetIncompleteShift(newNodeSchedulare, shiftsContainer);

                            // modify schdulare
                            currShiftToAssin.Workers.Remove(currShiftToAssin.Workers.FirstOrDefault(x => x.Name.IsNullOrEmpty()));
                            currShiftToAssin.Workers.Add(new Worker()
                            {
                                Name = emp
                            });

                            // validate if the new state in tabu list - is yes ignore it
                            if (CloseSet.Contains(newNodeSchedulare))
                            {
                                if (!DEBUG)
                                {
                                    continue;
                                }

                                Console.WriteLine($"####### Tabu list filterd #######");

                                continue;
                            }

                            // add new node to the tree - currNode
                            var childNode = currStateNodeInOrderToReplaceEmp.AddChild(newNodeSchedulare);

                            // get new state
                            var newNodeState = GetSchedulareState(newNodeSchedulare, shiftsContainer, childNode);

                            // add new state to openSet
                            OpenSet.Add(newNodeState);

                            // DEBUG
                            PrintDebugData(shiftsContainer, newNodeState);
                        }
                        #endregion
                    }
                }
                ExplorationStopwatch.Stop();

                #endregion

                if (IsGoal())
                {
                    break;
                }
            }

            var ret = CurrentBestSolution;

            CurrentBestSolution = null;
            IsFinished          = false;
            ExecuteStopwatch.Reset();

            return(ret);
        }
Esempio n. 18
0
        public override SchedulareState Execute(Schedulare schedulare, ShiftsContainer shiftsContainer)
        {
            InitParams(schedulare, shiftsContainer);

            var schedulareState = GetSchedulareState(schedulare.DeepClone(), shiftsContainer, TreeRoot);

            OpenSet.Add(schedulareState);

            ExecuteStopwatch.Start();

            while (!OpenSet.IsEmpty)
            {
                var currState = OpenSet.FindMin();

                OpenSet.DeleteMin();

                CloseSet.Add(currState);

                var currNode = currState.Node;

                UpdateCurrentBestSolution(currState);

                if (IsGoal() && IsSchedulareFull(currNode.Value, shiftsContainer))
                {
                    UpdateCurrentBestSolution(currState);
                    break;
                }

                // DEBUG
                PrintDebugData(shiftsContainer, currState);

                // if the current node is full schedulare but it is not goal yet
                // remove the node from open list and look for another solutions
                if (IsSchedulareFull(currNode.Value, shiftsContainer))
                {
                    OpenSet.DeleteMin();
                    CloseSet.Add(currState);
                    continue;
                }

                // create and add child nodes
                #region build new nodes

                foreach (var emp in shiftsContainer.EmployeeConstraints.Select(x => x.Name))
                {
                    var newNodeSchedulare = currNode.Value.DeepClone();

                    var currShiftToAssin = GetIncompleteShift(newNodeSchedulare, shiftsContainer);

                    // modify schdulare
                    currShiftToAssin.Workers.Add(new Worker()
                    {
                        Name = emp
                    });

                    // add new node to the tree - currNode
                    var childNode = currNode.AddChild(newNodeSchedulare);

                    // get new state
                    var newNodeState = GetSchedulareState(newNodeSchedulare, shiftsContainer, childNode);

                    // add new state to openSet
                    OpenSet.Add(newNodeState);
                }

                #endregion
            }

            // DEBUG
            PrintDebugData(shiftsContainer, CurrentBestSolution);

            var ret = CurrentBestSolution;

            CurrentBestSolution = null;
            IsFinished          = false;
            ExecuteStopwatch.Reset();

            return(ret);
        }
Esempio n. 19
0
        public static bool IsValidToAssign(Schedulare _schedulare, Day _schedulareDay, Shift _schedulareShift, Worker _randomEmployee)
        {
            try
            {
                // if employee is in the shift
                if (IsEmployeeInShift(_schedulareShift, _randomEmployee))
                {
                    return(false);
                }

                // if employee is in prev shift
                var   shiftIndex = _schedulareDay.Shifts.FindIndex(x => x.Name.CompareContent(_schedulareShift.Name));
                Shift shiftToValidate;
                if (shiftIndex > 0)
                {
                    shiftToValidate = _schedulareDay.Shifts[shiftIndex - 1];
                    if (IsEmployeeInShift(shiftToValidate, _randomEmployee))
                    {
                        return(false);
                    }
                }
                else if (!_schedulareDay.Name.ContainsContent("sunday"))
                // shiftIndex == 0 and we need to check the prev day last shift
                // at current logic we do not support 2 week therefore is its sunday we aprove
                {
                    var dayIndex      = _schedulare.Days.FindIndex(x => x.Name.ContainsContent(_schedulareDay.Name));
                    Day dayToValidate = _schedulare.Days[dayIndex - 1];
                    shiftToValidate = dayToValidate.Shifts.LastOrDefault();
                    if (IsEmployeeInShift(shiftToValidate, _randomEmployee))
                    {
                        return(false);
                    }
                }


                // if employee is in next shift
                shiftIndex = _schedulareDay.Shifts.FindIndex(x => x.Name.CompareContent(_schedulareShift.Name));
                if (shiftIndex < _schedulareDay.Shifts.Count() - 1)
                {
                    shiftToValidate = _schedulareDay.Shifts[shiftIndex + 1];
                    if (IsEmployeeInShift(shiftToValidate, _randomEmployee))
                    {
                        return(false);
                    }
                }
                else if (!_schedulareDay.Name.ContainsContent("saturday"))
                // shiftIndex == last shift and we need to check the next day first shift
                // at current logic we do not support 2 week therefore is its saturday we aprove
                {
                    var dayIndex      = _schedulare.Days.FindIndex(x => x.Name.ContainsContent(_schedulareDay.Name));
                    Day dayToValidate = _schedulare.Days[dayIndex + 1];
                    shiftToValidate = dayToValidate.Shifts.FirstOrDefault();
                    if (IsEmployeeInShift(shiftToValidate, _randomEmployee))
                    {
                        return(false);
                    }
                }
                return(true);
            }
            catch (Exception e)
            {
                ApeandToFile(e.ToString());
            }
            return(default);
Esempio n. 20
0
 public abstract SchedulareState Execute(Schedulare schedulare, ShiftsContainer shiftsContainer);