public IEnumerable <IRLVItemDisplay> GetMetricSum(Item[] items) { var retVal = new List <IRLVItemDisplay>(); double[] metrics = new double[10]; foreach (var item in items) { var itemMetrics = PlanogramOptimizer.GetCalculatedWeightedMetricArray(item, Parent.SimulationSettings); for (int i = 0; i < itemMetrics.Length; i++) { metrics[i] += itemMetrics[i]; } } for (int i = 0; i < metrics.Length; i++) { retVal.Add(new RLVItemDisplay() { Name = $"Metric {i + 1}", Value = metrics[i] }); } return(retVal); }
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 PlanogramOptResults ScorePilot() { PlanogramOptResults retVal = new PlanogramOptResults(); var shelves = new List <Shelf>(); double totalMetricScore = 0; int slotNumber = 0; Dictionary <int, int> itemDict = new Dictionary <int, int>(); bool hasExceedMax = false; for (int i = 0; i < simSettings.NumShelves; i++) { Shelf shelfInstance = new Shelf(); for (int p = 0; p < simSettings.NumSlots; p++) { var inputs = new BasicMLData(1); inputs[0] = slotNormalizer.Normalize(slotNumber); IMLData output = network.Compute(inputs); int index = Convert.ToInt32(itemNormalizer.DeNormalize(output[0])); Item itemReference = items[index]; if (!hasExceedMax) { hasExceedMax = !(CheckDuplicateItem(itemDict, index)); } // 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; shelfInstance.Add(itemReference, itemMetricScore); slotNumber++; } shelves.Add(shelfInstance); } retVal.Shelves = shelves; retVal.Score = (hasExceedMax) ? 0 : totalMetricScore; retVal.TimeElapsed = DateTime.Now - simSettings.StartedOn; return(retVal); }
/// <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, CancellationToken?cancelToken = null) { 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(); output.TimeElapsed = 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 >= SimulationSettings.NUM_SCORE_HITS)) { break; } if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested) { return(output); } } return(output); }
private void runSlmBtn_Click(object sender, RoutedEventArgs e) { selectedSlotIndex = -1; _row = -1; _col = -1; itemRow = -1; itemCol = -1; SimulationPanel simPanel = new SimulationPanel(); simPanel.SetSimSettings(simSettings); bool?result = simPanel.ShowDialog(); if (result.HasValue && result.Value == true) { // resets grid to default usePerfColor = false; FillGrid(planogram, Colors.LightGray); if (headToHead) { FillGrid(planogramTensorflow, Colors.LightGray); } // disable control buttons //statusTxt.Text = statusTxtTensor.Text = ""; statusTxtTensor.Text = "Waiting for RLM to finish running..."; 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; simSettings.HiddenLayers = simPanel.HiddenLayers; simSettings.HiddenLayerNeurons = simPanel.HiddenLayerNeurons; targetScoreTxt.Text = ""; if (simSettings.SimType == SimulationType.Score) { targetScoreLbl.Visibility = Visibility.Visible; targetScoreTxt.Visibility = Visibility.Visible; targetScoreTxt.Text = simSettings.Score.Value.ToString("n"); targetScoreTxt2.Visibility = Visibility.Visible; targetScoreTxt2.Text = simSettings.Score.Value.ToString("n"); } else { targetScoreLbl.Visibility = Visibility.Hidden; targetScoreTxt.Visibility = Visibility.Hidden; targetScoreTxt2.Visibility = Visibility.Hidden; } if (simSettings.SimType == SimulationType.Sessions) { sessionPerBatchLbl.Visibility = Visibility.Hidden; sessionPerBatchTxt.Visibility = Visibility.Hidden; } else { sessionPerBatchLbl.Visibility = Visibility.Visible; sessionPerBatchTxt.Visibility = Visibility.Visible; } Logger.Clear(); string dbIdentifier = "RLM_planogram_" + Guid.NewGuid().ToString("N"); // instantiate visualizer with this window as its parent reference visualizer = new RLVOutputVisualizer(this); core = new RLVCore(dbIdentifier); // subscribe mainwindow to the comparison event //visualizer.LearningComparisonDisplayResultsEvent += DisplayLearningComparisonResults; // 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 TempRLVContainerPanel(core, visualizer); //this.Top = 20; //tmpPanel.Top = this.Top; //this.Height = tmpPanel.Height; //tmpPanel.Left = 10; //this.Left = tmpPanel.Width + tmpPanel.Left; //tmpPanel.Visibility = Visibility.Hidden; 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); } // let's tensorflow (or other listeners) know that it should start training //OnSimulationStart?.Invoke(items, simSettings); //return; // initialize and start RLM training optimizer = new PlanogramOptimizer(items, simSettings, this.UpdateRLMResults, this.UpdateRLMStatus, Logger, dbIdentifier); //optimizer.OnSessionDone += Optimizer_OnSessionDone; optimizer.StartOptimization(tokenSource.Token); }); } }