[SuppressMessage("ReSharper", "AccessToModifiedClosure")] // Closure is always modified after use public void SpinWaitForExchangeWithContext() { const int NumIterations = 10_000; var runner = NewRunner(new DummyImmutableRef("0", 0L)); // (Func<T, TContext, T>, T) var valuesArr = Enumerable.Range(0, NumIterations + 1) .Select(i => new DummyImmutableRef((-i).ToString(), i)) .ToArray(); runner.GlobalSetUp = (target, _) => target.Value = valuesArr[0]; runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.LongProp); FastAssertEqual((-NumIterations).ToString(), target.Value.StringProp); }; runner.ExecuteSingleWriterSingleReaderTests( target => { for (var i = 0; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange((c, ctx) => ctx[c.LongProp + 1], valuesArr, valuesArr[nextVal]); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } }, target => { for (var i = 1; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange((c, ctx) => valuesArr[c.LongProp + 1], valuesArr, valuesArr[nextVal]); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } } ); runner.AllThreadsTearDown = null; // (T, Func<T, T, TContext, bool>) valuesArr = Enumerable.Range(0, NumIterations + 1) .Select(i => new DummyImmutableRef(i.ToString(), i)) .ToArray(); runner.GlobalSetUp = (target, _) => target.Value = valuesArr[0]; runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.LongProp); FastAssertEqual(NumIterations.ToString(), target.Value.StringProp); }; runner.ExecuteSingleWriterSingleReaderTests( target => { for (var i = 0; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange(valuesArr[nextVal + 1], (c, n, ctx) => n.LongProp == c.LongProp + ctx, 1); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>(nextVal.ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((nextVal + 1).ToString(), exchRes.CurrentValue.StringProp); } }, target => { for (var i = 1; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange(valuesArr[nextVal + 1], (c, n, ctx) => n.LongProp == c.LongProp + ctx, 1); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>(nextVal.ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((nextVal + 1).ToString(), exchRes.CurrentValue.StringProp); } } ); runner.AllThreadsTearDown = null; // (Func<T, TMapContext, T>, Func<T, T, TPredicateContext, bool>) valuesArr = Enumerable.Range(0, NumIterations + 1) .Select(i => new DummyImmutableRef((-i).ToString(), i)) .ToArray(); runner.GlobalSetUp = (target, _) => target.Value = valuesArr[0]; runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.LongProp); FastAssertEqual((-NumIterations).ToString(), target.Value.StringProp); }; runner.ExecuteSingleWriterSingleReaderTests( target => { for (var i = 0; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange((c, ctx) => ctx[c.LongProp + 1], valuesArr, (c, n, ctx) => n.LongProp == c.LongProp + ctx && c.LongProp == nextVal, 1); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } }, target => { for (var i = 1; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange((c, ctx) => ctx[c.LongProp + 1], valuesArr, (c, n, ctx) => n.LongProp == c.LongProp + ctx && c.LongProp == nextVal, 1); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } } ); runner.AllThreadsTearDown = null; // (Func<T, TContext, T>, Func<T, T, bool>) valuesArr = Enumerable.Range(0, NumIterations + 1) .Select(i => new DummyImmutableRef((-i).ToString(), i)) .ToArray(); runner.GlobalSetUp = (target, _) => target.Value = valuesArr[0]; runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.LongProp); FastAssertEqual((-NumIterations).ToString(), target.Value.StringProp); }; runner.ExecuteSingleWriterSingleReaderTests( target => { for (var i = 0; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange((c, ctx) => valuesArr[c.LongProp + ctx], 1, (c, n) => n.LongProp == c.LongProp + 1 && c.LongProp == nextVal); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } }, target => { for (var i = 1; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange((c, ctx) => valuesArr[c.LongProp + ctx], 1, (c, n) => n.LongProp == c.LongProp + 1 && c.LongProp == nextVal); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } } ); runner.AllThreadsTearDown = null; // (Func<T, T>, Func<T, T, TContext, bool>) valuesArr = Enumerable.Range(0, NumIterations + 1) .Select(i => new DummyImmutableRef((-i).ToString(), i)) .ToArray(); runner.GlobalSetUp = (target, _) => target.Value = valuesArr[0]; runner.AllThreadsTearDown = target => { FastAssertEqual(NumIterations, target.Value.LongProp); FastAssertEqual((-NumIterations).ToString(), target.Value.StringProp); }; runner.ExecuteSingleWriterSingleReaderTests( target => { for (var i = 0; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange(c => valuesArr[c.LongProp + 1], (c, n, ctx) => n.LongProp == c.LongProp + ctx && c.LongProp == nextVal, 1); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } }, target => { for (var i = 1; i < NumIterations; i += 2) { var nextVal = i; var exchRes = target.SpinWaitForExchange(c => valuesArr[c.LongProp + 1], (c, n, ctx) => n.LongProp == c.LongProp + ctx && c.LongProp == nextVal, 1); AssertAreEqual(nextVal, exchRes.PreviousValue.LongProp); AssertAreEqual(nextVal + 1, exchRes.CurrentValue.LongProp); FastAssertEqual <string>((-nextVal).ToString(), exchRes.PreviousValue.StringProp); FastAssertEqual <string>((-(nextVal + 1)).ToString(), exchRes.CurrentValue.StringProp); } } ); runner.AllThreadsTearDown = null; }
///////////////////////////////////////////////////////////////////// // Private Helper Methods ///////////////////////////////////////////////////////////////////// /// <summary> /// Constructs and trains a neural network, using the user selected /// settings, to fit a model to the selected dataset. /// /// Training continues until the maximum number of iterations has /// been exceeded or the total network error is less than the set /// minimum network error value. In the former case the trained /// neural network is the network that achieved the minimum network /// error during the training process. /// </summary> /// <returns>0 if successful otherwise -1</returns> /// private int FitModel() { int result = 0; bool converged = false; bool invalidResult = false; double netError = -1; double minErr = double.MaxValue; NeuralNet minNet = new NeuralNet(); // keeps track of the network with the minimum network error NNetTrainer trainer = new NNetTrainer(); // this object trains the neural net // populate the training set data PopulateTrainingSet(); // initialize the trainer trainer.AddNewTrainingSet(mInputVecs, mTargetVecs); trainer.LearningConstant = LearnConst; trainer.Momentum = Momentum; // clear the neural network ready to fit the model data mNet.ClearNeuralNetwork(); // initialize the network mNet.NumInputs = 1; // a single input value (the 'x-value') mNet.NumOutputs = 1; // a single output value (the 'y-value') mNet.OutputUnitType = OutputFunction; mNet.OutputUnitSlope = OutputSlope; mNet.OutputUnitAmplify = OutputAmplify; // use a fixed architecture of one hidden layer mNet.AddLayer(NumberOfHiddenUnits, HiddenFunction, InitRange, HiddenSlope, HiddenAmplify); // carry out the training for (int i = 1; i <= NumIterations; i++) { trainer.TrainNeuralNet(mNet); netError = trainer.NetError * ScaleFactor; // check for an invalid result from the network trainer if (double.IsNaN(netError) || double.IsInfinity(netError)) { MessageBox.Show("The network trainer has produced an invalid result:\nNetwork Error = " + netError.ToString() + "\nThe training process has been stopped.\nPlease adjust the model settings and try again.", "ModelFit", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); invalidResult = true; result = -1; break; } if (netError < MinNetError) { // the solution has converged MessageBox.Show("The solution has converged after " + i.ToString() + " iterations.", "ModelFit", MessageBoxButtons.OK, MessageBoxIcon.Information); // update the status bar this.PanelIterations.Text = "Iterations: " + i.ToString(); this.PanelNetError.Text = "Minimum Error: " + netError.ToString("G5"); converged = true; break; } // keep track of the minimum error value if (netError < minErr) { // copy the state of the neural net at the minimum error value minNet.CopyNeuralNet(mNet); minErr = netError; } // show the current progress if (i % 100 == 0) { this.PanelIterations.Text = "Iterations: " + i.ToString(); this.PanelNetError.Text = "Network Error: " + netError.ToString("G5"); Update(); } trainer.ResetNetError(); } if (!converged && !invalidResult) { // the solution has not converged within the given number of iterations MessageBox.Show("The solution has not converged.\n" + "The minimum error value was: " + minErr.ToString("G5") + "\n" + "The neural network that achieved this minimum will be used to fit the model.", "ModelFit", MessageBoxButtons.OK, MessageBoxIcon.Information); // copy the net with settings at the minimum error value mNet.CopyNeuralNet(minNet); // update the status bar this.PanelIterations.Text = "Iterations: " + NumIterations.ToString(); this.PanelNetError.Text = "Minimum Error: " + minErr.ToString("G5"); } // show the output in excel - if requested if (ExcelOutputCkBox.Checked && !invalidResult) { ShowOutputInExcel(mNet); } return(result); }