public PlanogramOptimizerEncog(Item[] items, SimulationSettings simSettings, UpdateUINonRLMCallback updateUI = null, UpdateStatusCallback updateStatus = null, SimulationCsvLogger logger = null, bool anneal = true)
        {
            updateStatus?.Invoke("Initializing...");

            //this.items = items;
            this.simSettings  = simSettings;
            this.logger       = logger;
            this.updateUI     = updateUI;
            this.updateStatus = updateStatus;

            network        = CreateNetwork();
            planogramScore = new PlanogramScore()
            {
                SimSettings = simSettings,
                Items       = items,
                UpdateUI    = updateUI,
                Logger      = logger
            };

            if (anneal)
            {
                train = new NeuralSimulatedAnnealing(network, planogramScore, 10, 2, (simSettings.SimType == SimulationType.Sessions) ?  1 : 10); // todo make the # of cycles an input for users?
            }
            else
            {
                train = new MLMethodGeneticAlgorithm(() => {
                    ((IMLResettable)network).Reset();
                    return(network);
                }, planogramScore, 500);
            }
        }
        /// <summary>
        /// Instantiates a new instance of the plangoram optimizer
        /// </summary>
        /// <param name="items">The dataset (items with their attributes and metrics) for the RLM to learn from</param>
        /// <param name="simSettings">Holds data which dictates what type of simulation to run and for how long. Also holds the weights metrics and other general settings</param>
        /// <param name="updateUI">Callback function for sending the results of the optimization for each session</param>
        /// <param name="updateStatus">Callback function for sending the current status of the RLM</param>
        /// <param name="logger">Logs the per session stats and allows users to download the CSV file after the training</param>
        /// <remarks>Used a callback instead of an event because we worry that the display might not keep up with the optimization. You can disable the display by setting it in the Simulation panel</remarks>
        public PlanogramOptimizer(Item[] items, RPOCSimulationSettings simSettings, UpdateUICallback updateUI = null, UpdateStatusCallback updateStatus = null, SimulationCsvLogger logger = null, string dbIdentifier = null)
        {
            this.logger      = logger;
            this.items       = items.ToArray();
            this.simSettings = simSettings;
            UpdateUI         = updateUI;
            UpdateStatus     = updateStatus;
            if (ENABLE_RLM_OUTPUT_LIMITER)
            {
                currentItemIndexes = new List <int>();
            }

            UpdateStatus?.Invoke("Initializing...");

            // creates the network (and the underlying DB) with a unique name to have a different network everytime you run a simulation
            IRlmDbData rlmDbData = new RlmDbDataSQLServer(dbIdentifier != null ? dbIdentifier : "RLM_planogram_" + Guid.NewGuid().ToString("N"));

            //IRlmDbData rlmDbData = new RlmDbDataPostgreSqlServer(dbIdentifier != null ? dbIdentifier : "RLM_planogram_" + Guid.NewGuid().ToString("N"));
            network = new RlmNetwork(rlmDbData);

            // checks if the network structure already exists
            // if not then we proceed to define the inputs and outputs

            inputType = RLM.Enums.RlmInputType.Distinct;
            if (!network.LoadNetwork("planogram"))
            {
                string int32Type = typeof(Int32).ToString();

                var inputs = new List <RlmIO>();
                //inputs.Add(new RlmIO() { Name = "Shelf", DotNetType = int32Type, Min = 1, Max = simSettings.NumShelves, Type = RLM.Enums.RlmInputType.Linear });
                inputs.Add(new RlmIO()
                {
                    Name = "Slot", DotNetType = int32Type, Min = 1, Max = simSettings.NumSlots * simSettings.NumShelves, Type = inputType
                });

                var outputs = new List <RlmIO>();
                outputs.Add(new RlmIO()
                {
                    Name = "Item", DotNetType = int32Type, Min = 0, Max = this.items.Length - 1
                });

                // change Max to any number above 1 (and must not be go beyond the NumSlots value) to have multiple facings
                //outputs.Add(new RlmIO() { Name = "NumFacings", DotNetType = int32Type, Min = 1, Max = 1 });

                // creates the network
                network.NewNetwork("planogram", inputs, outputs);
            }
        }