private void UpdateRLMResults(PlanogramOptResultsSettings results, bool enableSimDisplay)
        {
            enableSimDisplay = enableSimulation;
            Dispatcher.Invoke(() =>
            {
                if (enableSimDisplay)
                {
                    currentResults = results;
                    FillGrid(planogram, results.Shelves, false, ItemAttributes_MouseEnter, ItemAttributes_MouseLeave);
                }

                if (core.IsComparisonModeOn)
                {
                    DisplayLearningComparisonResults(tmpSelectedData, tmpComparisonData);
                }
                else
                {
                    string scoreText   = (simSettings.SimType == SimulationType.Score) ? $"{results.Score.ToString("#,###.##")} ({results.NumScoreHits})" : results.Score.ToString("#,###.##");
                    scoreTxt.Text      = scoreText;
                    sessionRunTxt.Text = results.CurrentSession.ToString();
                    timElapseTxt.Text  = results.TimeElapsed.ToString();//string.Format("{0:D2}:{1:D2}:{2:D2}.{3:D3}", results.TimeElapsed.Hours, results.TimeElapsed.Minutes, results.TimeElapsed.Seconds, results.TimeElapsed.Milliseconds);
                    minScoretxt.Text   = results.MinScore.ToString("#,###.##");
                    maxScoreTxt.Text   = results.MaxScore.ToString("#,###.##");
                    //engineTxt.Text = "RLM";
                    averageScoreTxt.Text      = results.AvgScore.ToString("#,###.##");
                    averageScoreOf10Txt.Text  = results.AvgLastTen.ToString("#,###.##");
                    currentRandomnessTxt.Text = results.CurrentRandomnessValue.ToString();
                    startRandomnessTxt.Text   = results.StartRandomness.ToString();
                    endRandomnessTxt.Text     = results.EndRandomness.ToString();
                    sessionPerBatchTxt.Text   = results.SessionsPerBatch.ToString();
                    inputTypeTxt.Text         = results.InputType;
                }
            });
        }
Beispiel #2
0
        private void UpdateRLMResults(PlanogramOptResultsSettings results, bool enableSimDisplay)
        {
            if (enableSimDisplay)
            {
                Task.Delay(1).Wait();
            }

            Dispatcher.Invoke(() =>
            {
                currentResults = results;
                if (enableSimDisplay && !core.IsComparisonModeOn)
                {
                    FillGrid(gridIceCreamShelves, results.Shelves, false, ItemAttributes_MouseEnter, ItemAttributes_MouseLeave);
                }

                if (core.IsComparisonModeOn)
                {
                    DisplayLearningComparisonResults(tmpSelectedData, tmpComparisonData);
                }
                else
                {
                    string scoreText     = (simSettings.SimType == SimulationType.Score) ? $"{results.Score.ToString("c")} ({results.NumScoreHits})" : results.Score.ToString("c");
                    txtCurrentScore.Text = scoreText;

                    //sessionRunTxt.Text = results.CurrentSession.ToString();
                    txtTimeElapsed.Text = results.TimeElapsed.ToString();
                    //txtMinScore.Text = results.MinScore.ToString("#,###.##");
                    txtMaxScore.Text = results.MaxScore.ToString("c");
                    //txtAverageScore.Text = results.AvgScore.ToString("#,###.##");
                    //txtAverageOfTenScores.Text = results.AvgLastTen.ToString("#,###.##");
                    //txtCurrentRandomnes.Text = results.CurrentRandomnessValue.ToString();
                    //txtStartRandomnes.Text = results.StartRandomness.ToString();
                    //txtEndRandomnes.Text = results.EndRandomness.ToString();
                    //txtSessionPerBatch.Text = results.SessionsPerBatch.ToString();
                    //txtInputType.Text = results.InputType;
                }
            });
        }
Beispiel #3
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, 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);
        }