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); }
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 }); }
/// <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); } } }
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; } } }
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); }
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()); }
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); }
protected override void PrintDebugData(ShiftsContainer shiftsContainer, SchedulareState state) { if (!DEBUG) { return; } Console.WriteLine($"_threshold - {_threshold}"); base.PrintDebugData(shiftsContainer, state); }
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)); }
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(); }
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); }
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);
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); }
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()); }
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); } }
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); }
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); }
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); }
public abstract SchedulareState Execute(Schedulare schedulare, ShiftsContainer shiftsContainer);