Esempio n. 1
0
        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);
        }
Esempio n. 3
0
        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();
                });
            }
        }
Esempio n. 4
0
        /// <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);
        }