private IEnumerable <Shelf> GetShelfData(RlmLearnedSessionDetails data) { var shelves = new List <Shelf>(); IDictionary <string, RlmIODetails> inputDict = data.Inputs.Where(a => a.CycleScore == 1).ToDictionary(a => a.Value, a => a); IDictionary <long, RlmIODetails> outputDict = data.Outputs.Where(a => a.CycleScore == 1).ToDictionary(a => a.CaseId, a => a); int numSlots = simSettings.NumShelves * simSettings.NumSlots; var shelf = new Shelf(); for (int i = 1; i <= numSlots; i++) { var input = inputDict[i.ToString()]; var output = outputDict[input.CaseId]; Item itemReference = itemsCache[Convert.ToInt32(output.Value)]; shelf.Add(itemReference, PlanogramOptimizer.GetCalculatedWeightedMetrics(itemReference, simSettings)); if (i % simSettings.NumSlots == 0) { shelves.Add(shelf); shelf = new Shelf(); } } return(shelves); }
public IEnumerable <IRLVItemDisplay> GetMetricSum(Item[] items) { var retVal = new List <IRLVItemDisplay>(); double[] metrics = new double[5]; foreach (var item in items) { var itemMetrics = PlanogramOptimizer.GetCalculatedWeightedMetricArray(item, Parent.SimulationSettings); for (int i = 0; i < itemMetrics.Length; i++) { metrics[i] += itemMetrics[i]; } } retVal.Add(new RLVItemDisplay() { Name = "Revenue", Value = metrics[0] }); retVal.Add(new RLVItemDisplay() { Name = "Sales", Value = metrics[1] }); retVal.Add(new RLVItemDisplay() { Name = "Customer Satisfaction", Value = metrics[2] }); retVal.Add(new RLVItemDisplay() { Name = "Sales Per Day", Value = metrics[3] }); retVal.Add(new RLVItemDisplay() { Name = "Reviews Per Day", Value = metrics[4] }); return(retVal); }
private void startOptimizing() { trainingOverlay.Visibility = Visibility.Visible; selectedSlotIndex = -1; _row = -1; _col = -1; itemRow = -1; itemCol = 1; SimulationPanel simPanel = new SimulationPanel(mock); simPanel.SetSimSettings(simSettings); //bool? result = simPanel.ShowDialog(); simPanel.btnRun_Click(null, null); //if (result.HasValue && result.Value == true) { // resets grid to default FillGrid(gridIceCreamShelves, Colors.LightGray); EnableControlButtons(false); // set simulation settings simSettings.SimType = simPanel.SimType; simSettings.Sessions = simPanel.Sessions; simSettings.Hours = simPanel.Hours; simSettings.Score = simPanel.Score; simSettings.EnableSimDisplay = simPanel.EnableSimDisplay; simSettings.DefaultScorePercentage = simPanel.simScoreSlider.Value; txtTargetScore.Text = ""; if (simSettings.SimType == SimulationType.Score) { txtTargetScore.Text = simSettings.Score.Value.ToString("n"); } else { txtTargetScore.Visibility = Visibility.Hidden; } //if (simSettings.SimType == SimulationType.Sessions) //{ // lblSessionPerBatch.Visibility = Visibility.Hidden; // txtSessionPerBatch.Visibility = Visibility.Hidden; //} //else //{ // lblSessionPerBatch.Visibility = Visibility.Visible; // txtSessionPerBatch.Visibility = Visibility.Visible; //} string dbIdentifier = "RLM_planogram_" + Guid.NewGuid().ToString("N"); // instantiate visualizer with this window as its parent reference visualizer = new RLVOutputVisualizer(this); rlmDbData = new RlmDbDataSQLServer(dbIdentifier); //rlmDbData = new RlmDbDataPostgreSqlServer(dbIdentifier); core = new RLVCore(rlmDbData); // open temporary RLV container panel // todo this must be embeded in this Window instead of the temporary container if (rlvPanel != null) { rlvPanel.Close(); } rlvPanel = new VisualizerWindow(core, visualizer); Task.Run(() => { // get items from db as well as the min and max metric scores as we need that for the calculation later on Item[] items; //using (PlanogramContext ctx = new PlanogramContext()) { //MockData mock = new MockData(ctx); items = itemsCache = mock.GetItemsWithAttr(); simSettings.ItemMetricMin = mock.GetItemMinimumScore(simSettings); simSettings.ItemMetricMax = mock.GetItemMaximumScore(simSettings); } // initialize and start RLM training optimizer = new PlanogramOptimizer(items, simSettings, this.UpdateRLMResults, this.UpdateRLMStatus, Logger, dbIdentifier, OnRLMDataPersistProgress); //optimizer.OnSessionDone += Optimizer_OnSessionDone; optimizer.StartOptimization(); }); } }
/// <summary> /// Does training or prediction for a set number of sessions /// </summary> /// <param name="sessions">Number of session to train/predict for</param> /// <param name="learn">Lets the RLM know if we are training or predicting</param> /// <returns>The final output for the training or prediction</returns> private PlanogramOptResults Optimize(int sessions, bool learn = true, bool enablePlanogramDisplay = false) { var output = new PlanogramOptResultsSettings(); // holds the unique SKUs that are already in the planogram. Ensures there are no duplicate SKUs var hashedSku = new HashSet <int>(); var itemDict = new Dictionary <int, int>(); var shelves = new List <Shelf>(); double totalMetricScore = 0; for (int i = 0; i < sessions; i++) { // reset for next session shelves.Clear(); hashedSku.Clear(); itemDict.Clear(); ResetCurrentItemIndexes(); totalMetricScore = 0; totalSessions++; DateTime startSession = DateTime.Now; // starts the session. we need to save the session ID as we will pass it to the cycle.Run later on long sessionId = network.SessionStart(); int numSlotFlattened = 0; // iterates for how many number of shelves our planogram has for (int shelf = 1; shelf <= simSettings.NumShelves; shelf++) { // this shelf instance will hold the items the RLM will output var shelfInstance = new Shelf() { Number = shelf }; int itemIndex; int numFacings; // iterates for how many number of slots on each shelf // notice that the slot is incremented depending on how many number of facings was outputed by the RLM for (int slot = 1; slot <= simSettings.NumSlots; slot += numFacings) { itemIndex = -1; numFacings = -1; bool isValid = false; numSlotFlattened++; do { // create the inputs with their corresponding values var inputs = new List <RlmIOWithValue>(); //inputs.Add(new RlmIOWithValue(network.Inputs.First(a => a.Name == "Shelf"), shelf.ToString())); //inputs.Add(new RlmIOWithValue(network.Inputs.First(a => a.Name == "Slot"), slot.ToString())); inputs.Add(new RlmIOWithValue(network.Inputs.First(a => a.Name == "Slot"), numSlotFlattened.ToString())); var rlmItemOutput = network.Outputs.FirstOrDefault(); var rlmIdeas = new List <RlmIdea>() { new RlmOutputLimiter(rlmItemOutput.ID, currentItemIndexes.Count - 1, GetEquivalentIndex) }; // runs a cycle with the sessionId passed in var cycle = new RlmCycle(); var rlmOutput = cycle.RunCycle(network, sessionId, inputs, learn, ideas: rlmIdeas); // get the outputs // the RLM outputs the item index so we will get the actual reference to the Item later on and // the second output is the number of facings that will show up on the plangram itemIndex = Convert.ToInt32(rlmOutput.CycleOutput.Outputs.First(a => a.Name == "Item").Value); numFacings = 1;//Convert.ToInt32(rlmOutput.CycleOutput.Outputs.First(a => a.Name == "NumFacings").Value); // we calculate how many remaining slots are there left to check for validity // because there might not be enough slots for what the number of facings was outputed by the RLM int remainingSlots = simSettings.NumSlots - shelfInstance.Items.Count(); bool isWithinLimit = CheckDuplicateItem(itemDict, itemIndex, numFacings); // here we check if the item is not a duplicate and that we have enough slots to fit the number of facings //if (hashedSku.Add(itemIndex) && remainingSlots >= numFacings) if (isWithinLimit && remainingSlots >= numFacings) { isValid = true; Item itemReference = items[itemIndex]; // we get the item reference using the index outputed by the RLM // with the item reference we will also have the Attributes which we need to calculate for the metrics double itemMetricScore = PlanogramOptimizer.GetCalculatedWeightedMetrics(itemReference, simSettings); // we add the item's metric score to totalMetricScore(which is our Session score in this case) // notice that we multplied it with the numFacings since that is how many will also show up on the planogram totalMetricScore += (itemMetricScore * numFacings); // add the items to the shelf container depending on how many facings for (int n = 0; n < numFacings; n++) { shelfInstance.Add(itemReference, itemMetricScore); } // A non-duplicate is good. network.ScoreCycle(rlmOutput.CycleOutput.CycleID, 1); } else { // we give the cycle a zero (0) score as it was not able to satisfy our conditions (punish it) isValid = false; network.ScoreCycle(rlmOutput.CycleOutput.CycleID, -1); //System.Diagnostics.Debug.WriteLine("try again"); } } while (!isValid); // if invalid, we redo the whole thing until the RLM is able to output an item that is unique and fits the remaining slot in the planogram } shelves.Add(shelfInstance); } // ends the session with the summed metric score for all items in the planogram network.SessionEnd(totalMetricScore); //System.Diagnostics.Debug.WriteLine($"Session #{i}, Score: {totalMetricScore}"); // set statistics and the optimized planogram shelves (and items inside them) output.Shelves = shelves; metricScoreHistory.Add(totalMetricScore); metricAvgLastTen.Enqueue(totalMetricScore); if (metricAvgLastTen.Count > 10) { metricAvgLastTen.Dequeue(); } output.Score = totalMetricScore; output.AvgScore = metricScoreHistory.Average(); output.AvgLastTen = metricAvgLastTen.Average(); output.MinScore = metricScoreHistory.Min(); output.MaxScore = metricScoreHistory.Max(); var timeRemaining = simSettings.EndsOn.Value - DateTime.Now; output.TimeElapsed = timeRemaining.TotalSeconds < 0 ? TimeSpan.Zero : timeRemaining; //DateTime.Now - simSettings.StartedOn; output.CurrentSession = totalSessions; output.MaxItems = MAX_ITEMS; output.StartRandomness = network.StartRandomness; output.EndRandomness = network.EndRandomness; output.SessionsPerBatch = DEFAULT_SESSIONS_PER_BATCH; output.InputType = inputType.ToString(); output.CurrentRandomnessValue = network.RandomnessCurrentValue; if (logger != null) { SimulationData logdata = new SimulationData(); logdata.Session = output.CurrentSession; logdata.Score = output.Score; logdata.Elapse = DateTime.Now - startSession; logger.Add(logdata); } // update the numScoreHits if the sim type is Score if (simSettings.SimType == SimulationType.Score) { if (totalMetricScore >= simSettings.Score.Value) { numScoreHits++; output.NumScoreHits = numScoreHits; } else { numScoreHits = 0; } } //OnSessionDone?.Invoke(output); // updates the results to the UI //bool enableSimDisplay = (!learn) ? true : (learn && simSettings.EnableSimDisplay) ? true : false; if (enablePlanogramDisplay) { output.MetricMin = simSettings.ItemMetricMin; output.MetricMax = simSettings.ItemMetricMax; output.CalculateItemColorIntensity(); } UpdateUI?.Invoke(output, enablePlanogramDisplay); // checks if we have already by passed the time or score that was set // if we did, then we stop the training and end it abruptly if ((simSettings.SimType == SimulationType.Time && simSettings.EndsOn.Value <= DateTime.Now) || (simSettings.SimType == SimulationType.Score && numScoreHits >= RPOCSimpleSimSettings.NUM_SCORE_HITS)) { break; } //System.Diagnostics.Debug.WriteLine("Randomness: " + network.RandomnessCurrentValue); } return(output); }