Beispiel #1
0
        public RlmNetwork CreateOrLoadNetwork(MazeInfo maze)
        {
            var rlmNet = new RlmNetwork("RLM_maze_" + maze.Name); //+ "_" + Guid.NewGuid().ToString("N"));

            rlmNet.DataPersistenceComplete += RlmNet_DataPersistenceComplete;
            rlmNet.DataPersistenceProgress += RlmNet_DataPersistenceProgress;

            if (!rlmNetCache.Contains("rlmNet"))
            {
                var expiration = DateTimeOffset.UtcNow.AddDays(1);
                rlmNetCache.Add("rlmNet", rlmNet, expiration);
            }
            else
            {
                rlmNet = (RlmNetwork)rlmNetCache.Get("rlmNet", null);
            }

            if (!rlmNet.LoadNetwork(maze.Name))
            {
                var inputs = new List <RlmIO>()
                {
                    new RlmIO("X", typeof(Int32).ToString(), 0, maze.Width - 1, RlmInputType.Distinct),
                    new RlmIO("Y", typeof(Int32).ToString(), 0, maze.Height - 1, RlmInputType.Distinct),
                };

                var outputs = new List <RlmIO>()
                {
                    new RlmIO("Direction", typeof(Int16).ToString(), 0, 3)
                };

                rlmNet.NewNetwork(maze.Name, inputs, outputs);
            }

            return(rlmNet);
        }
        public RLMPilot(bool learn = false, int numSessions = 50, int startRandomness = 30, int endRandomness = 0, int maxLinearBracket = 15, int minLinearBracket = 3)
        {
            string dbName = "RLM_lander_" + Guid.NewGuid().ToString("N");

            network = new RlmNetwork(dbName);
            network.DataPersistenceComplete += Network_DataPersistenceComplete;
            network.DataPersistenceProgress += Network_DataPersistenceProgress;

            if (!network.LoadNetwork(NETWORK_NAME))
            {
                var inputs = new List <RlmIO>();
                inputs.Add(new RlmIO("fuel", typeof(System.Int32).ToString(), 0, 200, RlmInputType.Linear));
                inputs.Add(new RlmIO("altitude", typeof(System.Double).ToString(), 0, 10000, RlmInputType.Linear));
                inputs.Add(new RlmIO("velocity", typeof(System.Double).ToString(), -LanderSimulator.TerminalVelocity, LanderSimulator.TerminalVelocity, RlmInputType.Linear));

                var outputs = new List <RlmIO>();
                outputs.Add(new RlmIO("thrust", typeof(System.Boolean).ToString(), 0, 1));

                network.NewNetwork(NETWORK_NAME, inputs, outputs);
            }

            Learn = learn;
            network.NumSessions      = numSessions;
            network.StartRandomness  = startRandomness;
            network.EndRandomness    = endRandomness;
            network.MaxLinearBracket = maxLinearBracket;
            network.MinLinearBracket = minLinearBracket;
        }
Beispiel #3
0
        public void CreateOrLoadNetwork(string dbIdentifier, int numSessions = 1, int startRandomness = 1, int endRandomness = 1)
        {
            network = new RlmNetwork(dbIdentifier);

            network.NumSessions     = numSessions;
            network.StartRandomness = startRandomness;
            network.EndRandomness   = endRandomness;

            //rlmNet.DataPersistenceComplete += RlmNet_DataPersistenceComplete;
            //rlmNet.DataPersistenceProgress += RlmNet_DataPersistenceProgress;

            if (!network.LoadNetwork(config.Name))
            {
                var inputs = new List <RlmIO>()
                {
                    //new RlmIO("X", typeof(Int32).ToString(), 0, config.Width - 1, RlmInputType.Distinct),
                    //new RlmIO("Y", typeof(Int32).ToString(), 0, config.Height - 1,  RlmInputType.Distinct),
                    new RlmIO("Move", typeof(Int32).ToString(), 0, 1000, RlmInputType.Distinct)
                };

                var outputs = new List <RlmIO>()
                {
                    new RlmIO("Direction", typeof(Int16).ToString(), 0, 3)
                };

                network.NewNetwork(config.Name, inputs, outputs);
            }
        }
Beispiel #4
0
        /// <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, RPOCSimpleSimSettings simSettings, UpdateUICallback updateUI = null, UpdateStatusCallback updateStatus = null, SimulationCsvLogger logger = null, string dbIdentifier = null, DataPersistenceProgressDelegate dataPersistProgress = null)
        {
            IsTrainingDone = false;

            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);

            if (dataPersistProgress != null)
            {
                network.DataPersistenceProgress += dataPersistProgress;
            }

            // 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);
            }
        }
Beispiel #5
0
        // for windowless version
        public RLMMazeTraveler(MazeInfo maze, bool learn = false, int numSessions = 1, int startRandomness = 1, int endRandomness = 1)
        {
            this.maze   = maze;
            Learn       = learn;
            rlmNetCache = MemoryCache.Default;

            rlmNet = CreateOrLoadNetwork(maze);

            rlmNet.NumSessions     = numSessions;
            rlmNet.StartRandomness = startRandomness;
            rlmNet.EndRandomness   = endRandomness;

            tmr.Elapsed += Tmr_Elapsed;
        }
        // for windowless version
        public RLMMazeTraveler(MazeInfo maze, bool learn = false, int numSessions = 1, int startRandomness = 1, int endRandomness = 1, Action <double, double> persistentProgressAct = null, Action persistentDoneAct = null)
        {
            this.maze   = maze;
            Learn       = learn;
            rlmNetCache = MemoryCache.Default;

            rlmNet = CreateOrLoadNetwork(maze);

            rlmNet.NumSessions     = numSessions;
            rlmNet.StartRandomness = startRandomness;
            rlmNet.EndRandomness   = endRandomness;

            tmr.Elapsed += Tmr_Elapsed;

            this.persistentProgressAct = persistentProgressAct;
            this.persistentDoneAct     = persistentDoneAct;
        }
Beispiel #7
0
        // for window version
        public RLMMazeTraveler(MazeInfo maze, MazeGame gameref, bool learn = false, int numSessions = 1, int startRandomness = 1, int endRandomness = 1, SetRandomnessLeftDelegate setRandomnessLeft = null)
            : base(gameref)
        {
            Learn = learn;
            GameRef.GameStartEvent += GameRef_GameStartEvent;
            GameRef.GameCycleEvent += GameRef_GameCycleEvent;
            //GameRef.GameOverEvent += GameRef_GameOverEvent;

            rlmNet = CreateOrLoadNetwork(maze);

            // Temporary, while RFactor not yet implemented
            rlmNet.NumSessions     = numSessions;
            rlmNet.StartRandomness = startRandomness;
            rlmNet.EndRandomness   = endRandomness;

            rlmNet.CycleComplete += Rlm_net_CycleComplete;

            SetRandomnessLeft = setRandomnessLeft;

            tmr.Elapsed += Tmr_Elapsed;
        }
        public void LogisticTrain()
        {
            Console.WriteLine("\nRLM network settings:");
            int sessions  = Util.GetInput("\nEnter Number of Session [default 100]: ", 100); //Gets user input for the number of tries the game will play
            int startRand = Util.GetInput("Enter Start Randomness [default 100]: ", 100);    //Gets user input for start randomness
            int endRand   = Util.GetInput("Enter End Randomness [default 0]: ", 0);          //Gets user input for end randomness

            var dbName                  = $"RLM_logistic_" + Guid.NewGuid().ToString("N");
            var networkName             = "Logicstics Network";
            LogisticSimulator simulator = null;

            IEnumerable <int> customerOrders = LogisticInitialValues.CustomerOrders;

            try
            {
                //IRlmDbData rlmDbData = new RlmDbDataPostgreSqlServer(dbName);
                IRlmDbData rlmDbData = new RlmDbDataSQLServer(dbName);
                RlmNetwork network   = new RlmNetwork(rlmDbData); //Make an instance of rlm_network passing the database name as parameter
                network.DataPersistenceComplete += Network_DataPersistenceComplete;
                network.DataPersistenceProgress += Network_DataPersistenceProgress;

                if (!network.LoadNetwork(networkName))
                {
                    var inputs = new List <RlmIO>()
                    {
                        new RlmIO("X", typeof(Int32).ToString(), 1, 1, RlmInputType.Distinct),
                    };

                    double minFrom = LogisticInitialValues.PlayerMinRange[0];
                    double minTo   = LogisticInitialValues.PlayerMinRange[1];
                    double maxFrom = LogisticInitialValues.PlayerMaxRange[0];
                    double maxTo   = LogisticInitialValues.PlayerMaxRange[1];
                    var    outputs = new List <RlmIO>()
                    {
                        new RlmIO("Retailer_Min", typeof(Int16).ToString(), minFrom, minTo),
                        new RlmIO("Retailer_Max", typeof(Int16).ToString(), maxFrom, maxTo),
                        new RlmIO("WholeSaler_Min", typeof(Int16).ToString(), minFrom, minTo),
                        new RlmIO("WholeSaler_Max", typeof(Int16).ToString(), maxFrom, maxTo),
                        new RlmIO("Distributor_Min", typeof(Int16).ToString(), minFrom, minTo),
                        new RlmIO("Distributor_Max", typeof(Int16).ToString(), maxFrom, maxTo),
                        new RlmIO("Factory_Min", typeof(Int16).ToString(), minFrom, minTo),
                        new RlmIO("Factory_Max", typeof(Int16).ToString(), maxFrom, maxTo),
                        new RlmIO("Factory_Units_Per_Day", typeof(Int16).ToString(), LogisticInitialValues.FactoryRange[0], LogisticInitialValues.FactoryRange[1]),
                    };

                    network.NewNetwork(networkName, inputs, outputs);
                }

                // execute it on another thread as not to block the RLM training
                Console.WriteLine("\nPress 'd' to show Data persistence progress\n");
                Task.Run(() =>
                {
                    while (!Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.D)
                    {
                        showDataPersistProgress = true;
                    }
                });

                network.NumSessions     = sessions; // num of sessioins default 100
                network.StartRandomness = startRand;
                network.EndRandomness   = endRand;

                simulator = new LogisticSimulator(LogisticInitialValues.StorageCost, LogisticInitialValues.BacklogCost, LogisticInitialValues.InitialInventory, LogisticInitialValues.InitialInventory, LogisticInitialValues.InitialInventory, LogisticInitialValues.InitialInventory);

                Stopwatch watch = new Stopwatch();
                watch.Start();
                Console.WriteLine("\n\nTraining:\n");
                IEnumerable <LogisticSimulatorOutput> predictedLogisticOutputs = null;

                network.ResetRandomizationCounter();

                for (int i = 0; i < sessions; i++)
                {
                    var sessId = network.SessionStart();

                    var inputs = new List <RlmIOWithValue>();
                    inputs.Add(new RlmIOWithValue(network.Inputs.First(), "1"));

                    var cycle   = new RlmCycle();
                    var outputs = cycle.RunCycle(network, sessId, inputs, true);

                    var simOutputs = outputs.CycleOutput.Outputs
                                     .Select(a => new LogisticSimulatorOutput()
                    {
                        Name = a.Name, Value = Convert.ToInt32(a.Value)
                    })
                                     .ToList();

                    simulator.ResetSimulationOutput();
                    simulator.Start(simOutputs, 50, customerOrders);

                    network.ScoreCycle(outputs.CycleOutput.CycleID, 0);
                    var totalCosts = simulator.SumAllCosts();
                    network.SessionEnd(totalCosts);

                    Console.WriteLine($"Session #{i + 1} \t Score: {Math.Abs(totalCosts).ToString("$#,##0"),10}");

                    if (i == sessions - 1)
                    {
                        predictedLogisticOutputs = simOutputs;
                    }
                }


                watch.Stop();

                Console.WriteLine("\nPredicted outputs:");
                string resultText = "";
                foreach (var item in predictedLogisticOutputs)
                {
                    resultText += "\n" + item.Name + ": " + item.Value;
                }

                Console.WriteLine(resultText);
                Console.WriteLine($"\nElapsed: {watch.Elapsed}");
                network.TrainingDone();
            }
            catch (Exception e)
            {
                if (e.InnerException != null && e.InnerException is RlmDefaultConnectionStringException)
                {
                    Console.WriteLine($"Error: {e.InnerException.Message}");
                }
                else
                {
                    Console.WriteLine($"ERROR: {e.Message}");
                }
            }
            Console.ReadLine();
        }
        private void MqttClient_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {
            string topic = e.Topic;
            string msg   = Encoding.UTF8.GetString(e.Message);

            if (topic == "init")
            {
                TOPIC_UID = msg; //Get unique id from client

                subscribe("create_load_network");
                subscribe("configure_network");
                subscribe("start_session");
                subscribe("run_cycle");
                subscribe("score_cycle");
                subscribe("end_session");
                subscribe("sessions");
                subscribe("session_cases");
                subscribe("io_details");
                subscribe("disconnect");

                publish(msg + "/init_result", TOPIC_UID);
            }
            else if (topic == createTopic("create_load_network"))
            {
                CreateLoadNetworkParams data = JsonConvert.DeserializeObject <CreateLoadNetworkParams>(msg);
                network = new RlmNetwork(data.RlmName);

                if (!network.LoadNetwork(data.NetworkName))
                {
                    IEnumerable <RlmIO> inputs  = data.Inputs.Select(a => new RlmIO(a.IOName, a.DotNetType, a.Min, a.Max, a.InputType)).ToList();
                    IEnumerable <RlmIO> outputs = data.Outputs.Select(a => new RlmIO(a.IOName, a.DotNetType, a.Min, a.Max)).ToList();

                    network.NewNetwork(data.NetworkName, inputs, outputs);
                }

                publish(createTopic("create_network_result"), "Network successfully loaded!");
            }
            else if (topic == createTopic("configure_network"))
            {
                RlmSettingsParams data = JsonConvert.DeserializeObject <RlmSettingsParams>(msg);

                network.NumSessions      = data.NumSessions;
                network.StartRandomness  = data.StartRandomness;
                network.EndRandomness    = data.EndRandomness;
                network.MaxLinearBracket = data.MaxLinearBracket;
                network.MinLinearBracket = data.MinLinearBracket;

                publish(createTopic("configure_result"), "Network successfully configured!");
            }
            else if (topic == createTopic("start_session"))
            {
                long sessionId = network.SessionStart();

                publish(createTopic("start_session_result"), sessionId.ToString());
            }
            else if (topic == createTopic("run_cycle"))
            {
                RunCycleParams data   = JsonConvert.DeserializeObject <RunCycleParams>(msg);
                var            retVal = new CycleOutputParams();


                var inputsCycle = new List <RlmIOWithValue>();
                foreach (var ins in data.Inputs)
                {
                    inputsCycle.Add(new RlmIOWithValue(network.Inputs.Where(item => item.Name == ins.IOName).First(), ins.Value));
                }

                var Cycle = new RlmCycle();
                RlmCyclecompleteArgs cycleOutput = null;

                // supervised training
                if (data.Outputs == null ||
                    (data.Outputs != null && data.Outputs.Count > 0))
                {
                    var outputsCycle = new List <RlmIOWithValue>();
                    foreach (var outs in data.Outputs)
                    {
                        outputsCycle.Add(new RlmIOWithValue(network.Outputs.First(a => a.Name == outs.IOName), outs.Value));
                    }

                    cycleOutput = Cycle.RunCycle(network, network.CurrentSessionID, inputsCycle, data.Learn, outputsCycle);
                }
                else // unsupervised training
                {
                    cycleOutput = Cycle.RunCycle(network, network.CurrentSessionID, inputsCycle, data.Learn);
                }

                if (cycleOutput != null)
                {
                    retVal = new CycleOutputParams {
                        RlmType = cycleOutput.RlmType, CycleId = cycleOutput.CycleOutput.CycleID
                    };
                    var outputs = cycleOutput.CycleOutput.Outputs;
                    for (int i = 0; i < outputs.Count(); i++)
                    {
                        RlmIOWithValue output = outputs.ElementAt(i);
                        retVal.Outputs.Add(new RlmIOWithValuesParams()
                        {
                            IOName = output.Name, Value = output.Value
                        });
                    }
                }

                var resultStr = JsonConvert.SerializeObject(retVal);

                publish(createTopic("run_cycle_result"), resultStr);
            }
            else if (topic == createTopic("score_cycle"))
            {
                ScoreCycleParams data = JsonConvert.DeserializeObject <ScoreCycleParams>(msg);

                network.ScoreCycle(data.CycleID, data.Score);

                publish(createTopic("score_cycle_result"), "Scoring cycle...");
            }
            else if (topic == createTopic("end_session"))
            {
                SessionEndParams data = JsonConvert.DeserializeObject <SessionEndParams>(msg);

                network.SessionEnd(data.SessionScore);

                publish(createTopic("end_session_result"), "Session ended!");
            }
            else if (topic == createTopic("sessions"))
            {
                dynamic data = JsonConvert.DeserializeObject <dynamic>(msg);


                string dbName = (String)data.RlmName;
                bool   withSignificantLearning = Convert.ToBoolean(((String)data.WithLearning).ToLower());
                int?   skip = Convert.ToInt32(((Int32)data.Skip));
                int?   take = Convert.ToInt32(((Int32)data.Take));

                if (skip == 0)
                {
                    skip = null;
                }

                if (take == 0)
                {
                    take = null;
                }

                string resultStr = "";
                if (withSignificantLearning)
                {
                    resultStr = JsonConvert.SerializeObject(getSessionsWithSignificantLearning(new RlmFilterResultParams {
                        Skip = skip, Take = take, RlmName = dbName
                    }));
                }
                else
                {
                    resultStr = JsonConvert.SerializeObject(getSessionHistory(new RlmFilterResultParams {
                        Skip = skip, Take = take, RlmName = dbName
                    }));
                }

                publish(createTopic("sessions_result"), resultStr);
            }
            else if (topic == createTopic("session_cases"))
            {
                RlmGetSessionCaseParams data = JsonConvert.DeserializeObject <RlmGetSessionCaseParams>(msg);

                RlmSessionCaseHistory hist = new RlmSessionCaseHistory(data.RlmName);

                var resultStr = JsonConvert.SerializeObject(hist.GetSessionCaseHistory(data.SessionId, data.Skip, data.Take));

                publish(createTopic("session_cases_result"), resultStr);
            }
            else if (topic == createTopic("io_details"))
            {
                RlmGetCaseIOParams data = JsonConvert.DeserializeObject <RlmGetCaseIOParams>(msg);

                RlmSessionCaseHistory hist = new RlmSessionCaseHistory(data.RlmName);

                var resultStr = JsonConvert.SerializeObject(hist.GetCaseIOHistory(data.CaseId, data.RneuronId, data.SolutionId));

                publish(createTopic("io_details_result"), resultStr);
            }
            else if (topic == createTopic("disconnect"))
            {
                if (MQTT_CLIENT != null && MQTT_CLIENT.IsConnected)
                {
                    MQTT_CLIENT.Disconnect();
                }
            }
        }
Beispiel #10
0
        static void Main(string[] args)
        {
            Console.WriteLine("XOR");
            Console.WriteLine("\nRLM settings");

            // user inputs for the RLM settings
            int sessions        = Util.GetInput("Number of sessions [default 50]: ", 50);
            int startRandomness = Util.GetInput("Start randomness [default 50]: ", 50);
            int endRandomness   = Util.GetInput("End randomness [default 0]: ", 0);

            // use Sql Server as Rlm Db
            IRlmDbData rlmDBData = new RlmDbDataSQLServer($"RLM_XOR_SAMPLE_{Guid.NewGuid().ToString("N")}");
            //IRlmDbData rlmDBData = new RlmDbDataPostgreSqlServer($"RLM_XOR_SAMPLE_{Guid.NewGuid().ToString("N")}");

            // the appended Guid is just to have a unique RLM network every time we run this example.
            // you can remove this or simply change the name to something static to use the same network all the time
            var rlmNet = new RlmNetwork(rlmDBData);

            // subscribe to events to know the status of the Data Persistence that works in the background
            rlmNet.DataPersistenceComplete += RlmNet_DataPersistenceComplete;
            rlmNet.DataPersistenceProgress += RlmNet_DataPersistenceProgress;

            // checks to see if the network already exists and loads it to memory
            if (!rlmNet.LoadNetwork("XOR_SAMPLE"))
            {
                // declare our inputs
                var ins = new List <RlmIO>();
                ins.Add(new RlmIO("XORInput1", typeof(bool).ToString(), 0, 1, RlmInputType.Distinct));
                ins.Add(new RlmIO("XORInput2", typeof(bool).ToString(), 0, 1, RlmInputType.Distinct));

                // declare our outputs
                var outs = new List <RlmIO>();
                outs.Add(new RlmIO("XOROutput", typeof(bool).ToString(), 0, 1));

                // creates a new network
                rlmNet.NewNetwork("XOR_SAMPLE", ins, outs);
            }

            // execute it on another thread as not to block the RLM training
            Console.WriteLine("\nPress 'd' to show Data persistence progress\n");
            Task.Run(() =>
            {
                while (!Console.KeyAvailable && Console.ReadKey(true).Key == ConsoleKey.D)
                {
                    showDataPersistProgress = true;
                }
            });

            // set rlm training settings
            rlmNet.NumSessions     = sessions;
            rlmNet.StartRandomness = startRandomness;
            rlmNet.EndRandomness   = endRandomness;

            Console.WriteLine("Training Session started");
            double sumOfCycleScores = 0;

            // this is just good practice, usually you need to call this when you want to do multiple trainings on the same network over and over again.
            // it resets the randomization of the RLM back to the beginning (start randomness) after each training set
            // i.e, training for 50 sessions, then training for another 50 sessions, and so on and so forth
            rlmNet.ResetRandomizationCounter();

            for (int i = 0; i < sessions; i++)
            {
                // start session
                long sessionId = rlmNet.SessionStart();
                sumOfCycleScores = 0;

                foreach (var xor in xorTable)
                {
                    //Populate input values
                    var invs = new List <RlmIOWithValue>();

                    // get value for Input1 and associate it with the Input instance
                    string input1Value = xor.Input1;
                    invs.Add(new RlmIOWithValue(rlmNet.Inputs.Where(item => item.Name == "XORInput1").First(), input1Value));

                    // get value for Input2 and associate it with the Input instance
                    string input2Value = xor.Input2;
                    invs.Add(new RlmIOWithValue(rlmNet.Inputs.Where(item => item.Name == "XORInput2").First(), input2Value));

                    //Build and run a new RlmCycle
                    var Cycle = new RlmCycle();
                    RlmCyclecompleteArgs result = Cycle.RunCycle(rlmNet, sessionId, invs, true);

                    // scores the RLM on how well it did for this cycle
                    // each cycle with a correct output is rewarded a 100 score, 0 otherwise
                    double score = ScoreCycle(result, xor);

                    sumOfCycleScores += score;

                    // sets the score
                    rlmNet.ScoreCycle(result.CycleOutput.CycleID, score);
                }

                Console.WriteLine($"Session #{i} - score: {sumOfCycleScores}");

                // end the session with the sum of the cycle scores
                // with the way the scoring is set, a perfect score would be 400 meaning all cycles got it right
                rlmNet.SessionEnd(sumOfCycleScores);
            }


            Console.WriteLine("Training Session ended");

            Console.WriteLine();
            Console.WriteLine("Predict:");

            // PREDICT... see how well the RLM learned
            // NOTE that the only difference with Predict from Training is that we passed 'false' to the learn argument on the Cycle.RunCycle() method
            // and of course, the inputs which we used our xor table to check if the RLM has learned as expected
            long SessionID = rlmNet.SessionStart();

            sumOfCycleScores = 0;

            foreach (var xor in xorTable)
            {
                var invs = new List <RlmIOWithValue>();
                invs.Add(new RlmIOWithValue(rlmNet.Inputs.First(a => a.Name == "XORInput1"), xor.Input1));
                invs.Add(new RlmIOWithValue(rlmNet.Inputs.First(a => a.Name == "XORInput2"), xor.Input2));

                RlmCycle             Cycle  = new RlmCycle();
                RlmCyclecompleteArgs result = Cycle.RunCycle(rlmNet, SessionID, invs, false);

                double score = ScoreCycle(result, xor, true);

                sumOfCycleScores += score;

                // sets the score
                rlmNet.ScoreCycle(result.CycleOutput.CycleID, score);
            }

            rlmNet.SessionEnd(sumOfCycleScores);

            // must call this to let the Data persistence know we are done training/predicting
            rlmNet.TrainingDone();

            Console.ReadLine();
        }