Example #1
0
        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);
        }
        /// <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);

                // 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 >= RPOCSimulationSettings.NUM_SCORE_HITS))
                {
                    break;
                }

                if (cancelToken.HasValue && cancelToken.Value.IsCancellationRequested)
                {
                    return(output);
                }
            }

            return(output);
        }
        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);

                    ////Actual Code
                    //IMLData output = network.Compute(inputs);
                    //int index = Convert.ToInt32(itemNormalizer.DeNormalize(output[0]));

                    int     index  = 1;
                    IMLData output = null;
                    //Test Code

                    do
                    {
                        output = network.Compute(inputs);
                        index  = Convert.ToInt32(itemNormalizer.DeNormalize(output[0]));
                    } while (index < 0 || index > items.Length - 1);



                    //// Gino Code for Genetic
                    //if (index < 0 || index > items.Length - 1)
                    //{
                    //    index = 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);
        }