/// <summary> /// This method will let the AI play the maze for one game (windowless) /// </summary> public MazeCycleOutcome Travel(int timerTimeout = 5000) { MazeGame game = new MazeGame(); game.traveler = this; game.InitGame(maze); MazeCycleOutcome outcome = new MazeCycleOutcome(); // Start AI Training currentSessionID = rlmNet.SessionStart(); SessionStarted?.Invoke(rlmNet.RandomnessCurrentValue); tmr.Interval = timerTimeout; tmr.Start(); timeout = 0; int movesCnt = 0; while (!outcome.GameOver && timeout == 0) { // set up input for x and y based on our current location on the maze var inputs = new List <RlmIOWithValue>() { new RlmIOWithValue(rlmNet.Inputs.First(a => a.Name == "X"), game.traveler.location.X.ToString()), new RlmIOWithValue(rlmNet.Inputs.First(a => a.Name == "Y"), game.traveler.location.Y.ToString()), }; // get AI output based on inputs RlmCycle cycle = new RlmCycle(); var aiResult = cycle.RunCycle(rlmNet, currentSessionID, inputs, Learn); var direction = Convert.ToInt16(aiResult.CycleOutput.Outputs.First().Value); // make the move outcome = game.CycleMaze(direction); // score AI output double score = ScoreAI(outcome, game.traveler); rlmNet.ScoreCycle(aiResult.CycleOutput.CycleID, score); MazeCycleComplete?.Invoke(game.traveler.location.X, game.traveler.location.Y, outcome.BumpedIntoWall); movesCnt++; } tmr.Stop(); // compute final score outcome.FinalScore = game.CalculateFinalScore(game.Moves); // End AI Training rlmNet.SessionEnd(outcome.FinalScore); SessionComplete?.Invoke(rlmNet.SessionCount, outcome.FinalScore, movesCnt); return(outcome); }
public void StartSimulation(int sessionNumber, bool showOutput = true) { var sim = new LanderSimulator(); var sessionId = network.SessionStart(); while (sim.Flying) { var inputs = new List <RlmIOWithValue>(); inputs.Add(new RlmIOWithValue(network.Inputs.First(a => a.Name == "fuel"), sim.Fuel.ToString())); inputs.Add(new RlmIOWithValue(network.Inputs.First(a => a.Name == "altitude"), Math.Round(sim.Altitude, 2).ToString())); inputs.Add(new RlmIOWithValue(network.Inputs.First(a => a.Name == "velocity"), Math.Round(sim.Velocity, 2).ToString())); var cycle = new RlmCycle(); watcher.Restart(); var cycleOutcome = cycle.RunCycle(network, network.CurrentSessionID, inputs, Learn); watcher.Stop(); TotalCycleTime.Add(watcher.ElapsedMilliseconds); bool thrust = Convert.ToBoolean(cycleOutcome.CycleOutput.Outputs.First(a => a.Name == "thrust").Value); if (thrust && showOutput && !Learn) { Console.WriteLine("@THRUST"); } var score = scoreTurn(sim, thrust); network.ScoreCycle(cycleOutcome.CycleOutput.CycleID, score); sim.Turn(thrust); if (showOutput && !Learn) { Console.WriteLine(sim.Telemetry()); } if (sim.Fuel == 0 && sim.Altitude > 0 && sim.Velocity == -LanderSimulator.TerminalVelocity) { break; } } if (showOutput) { Console.WriteLine($"Session #{ sessionNumber } \t Score: {sim.Score}"); } network.SessionEnd(lastScore = sim.Score); }
/// <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); }
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 MazeCycleOutcome Travel(bool learn, int?timerTimeout = null, CancellationToken?token = null, bool perMoveDisplay = false) { IMazeGame game = GetNewGameInstance(); MazeCycleOutcome outcome = new MazeCycleOutcome(); // Start AI Training var currentSessionID = network.SessionStart(); SessionStarted?.Invoke(network.RandomnessCurrentValue); recentMoves.Clear(); //tmr.Interval = timerTimeout; //tmr.Start(); //timeout = 0; int movesCnt = 1; while (!outcome.GameOver) // && timeout == 0) { if (token?.IsCancellationRequested == true) { break; } // set up input for x and y based on our current location on the maze var inputs = new List <RlmIOWithValue>() { //new RlmIOWithValue(network.Inputs.First(a => a.Name == "X"), game.traveler.location.X.ToString()), //new RlmIOWithValue(network.Inputs.First(a => a.Name == "Y"), game.traveler.location.Y.ToString()), new RlmIOWithValue(network.Inputs.First(a => a.Name == "Move"), movesCnt.ToString()) }; // get AI output based on inputs RlmCycle cycle = new RlmCycle(); var aiResult = cycle.RunCycle(network, currentSessionID, inputs, learn); var direction = Convert.ToInt16(aiResult.CycleOutput.Outputs.First().Value); // make the move outcome = game.CycleMaze(direction); // score AI output double score = 0.0; //score = ScoreAI(outcome, game.traveler); network.ScoreCycle(aiResult.CycleOutput.CycleID, score); if (timerTimeout.HasValue) { Task.Delay(timerTimeout.Value).Wait(); } if (perMoveDisplay) { MazeCycleComplete?.Invoke(game.traveler.location.X, game.traveler.location.Y, outcome.BumpedIntoWall); } if (!learn) { recentMoves.Add(new MoveDetails() { Direction = direction, MoveNumber = movesCnt }); } movesCnt++; } //tmr.Stop(); // compute final score outcome.FinalScore = game.CalculateFinalScore(game.Moves); // End AI Training network.SessionEnd(outcome.FinalScore); SessionComplete?.Invoke(network.SessionCount, outcome.FinalScore, movesCnt - 1); if (movesCnt > HighestMoveCount) { HighestMoveCount = movesCnt; } return(outcome); }
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(); } } }
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(); }