示例#1
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);
        }
示例#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
            });
        }
示例#3
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);
                }
            }
        }
示例#4
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;
                }
            }
        }
示例#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);
        }
示例#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());
        }
示例#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);
        }
示例#8
0
        protected override void PrintDebugData(ShiftsContainer shiftsContainer, SchedulareState state)
        {
            if (!DEBUG)
            {
                return;
            }

            Console.WriteLine($"_threshold - {_threshold}");
            base.PrintDebugData(shiftsContainer, state);
        }
示例#9
0
        private void UpdateSchefulareStatistics(ShiftsContainer shiftsContainer, SchedulareState algoResult, string algoString)
        {
            if (!_schedulareStatisticsList.ContainsKey(algoString))
            {
                _schedulareStatisticsList.AddOrUpdate(algoString, new SchedulareListStatistics());
            }
            var bfsSatisfaction = CommonLogic.GetPercentageOfSatisfaction(algoResult.Node.Value, shiftsContainer);

            _schedulareStatisticsList[algoString].SchedulareSatisfactionList.Add(new SchedulareSatisfaction(algoResult.Node.Value, bfsSatisfaction, shiftsContainer, algoResult.Weight,
                                                                                                            algoResult.ExecuteTime, algoResult.MostUnfortunateWorkerPer));
        }
示例#10
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();
        }
示例#11
0
        protected virtual void PrintDebugData(ShiftsContainer shiftsContainer, SchedulareState state)
        {
            if (!DEBUG)
            {
                return;
            }

            double percentageOfSatisfaction = CommonLogic.GetPercentageOfSatisfaction(state.Node.Value, shiftsContainer);

            Console.WriteLine($"Weight = {state.Weight}");
            Console.WriteLine($"Percentage of workes constrains satisfaction = {percentageOfSatisfaction}");
            CommonLogic.PrintSchedulare(state.Node.Value, shiftsContainer);
        }
示例#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);
示例#13
0
        private void PrintDebugData(ShiftsContainer shiftsContainer, SchedulareState state, string algoName)
        {
            Console.WriteLine(algoName);
            double percentageOfSatisfaction = CommonLogic.GetPercentageOfSatisfaction(state.Node.Value, shiftsContainer);

            Console.WriteLine($"Weight = {state.Weight}");
            Console.WriteLine($"Satisfaction = {percentageOfSatisfaction}");
            state.MostUnfortunateWorkerPer = CommonLogic.LocateAndPrintMostUnfortunateWorker(state.Node.Value, shiftsContainer);
            CommonLogic.PrintSchedulare(state.Node.Value, shiftsContainer);

            CommonLogic.ApeandToFile(algoName, FILENAME);
            CommonLogic.ApeandToFile($"Weight = {state.Weight}", FILENAME);
            CommonLogic.ApeandToFile($"Satisfaction = {percentageOfSatisfaction}", FILENAME);
            string schedulareStateJson = JsonConvert.SerializeObject(state.Node.Value);

            CommonLogic.ApeandToFile(schedulareStateJson, FILENAME);
            string shiftsContainerJson = JsonConvert.SerializeObject(shiftsContainer);

            CommonLogic.ApeandToFile(shiftsContainerJson, FILENAME);
        }
示例#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());
        }
示例#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);
            }
        }
示例#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);
        }
示例#17
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);
        }
示例#18
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);
        }
示例#19
0
 public abstract SchedulareState Execute(Schedulare schedulare, ShiftsContainer shiftsContainer);