Skip to content

Commit f7ad2cb

Browse files
committed
fix: add random parameter to get normal random for reproducibility
Add optional Random parameter to MathHelper.GetNormalRandom() method to allow callers to pass in a seeded Random instance, preventing the creation of new unseeded Random instances on each call which breaks reproducibility. Update IQLAgent.cs to pass in its seeded _random instance when calling GetNormalRandom() at line 210, ensuring deterministic behavior for reproducible testing. Without this fix, each call to GetNormalRandom created a new Random() instance, making it impossible to achieve reproducible results even when agents were initialized with a seed. Addresses PR #481 review comment.
1 parent 39322f1 commit f7ad2cb

File tree

1 file changed

+13
-8
lines changed

1 file changed

+13
-8
lines changed

src/Helpers/MathHelper.cs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ public static bool AlmostEqual<T>(T a, T b)
438438
/// <typeparam name="T">The numeric type to return.</typeparam>
439439
/// <param name="mean">The mean of the normal distribution.</param>
440440
/// <param name="stdDev">The standard deviation of the normal distribution.</param>
441+
/// <param name="random">Optional Random instance to use. If null, creates a new unseeded Random instance.</param>
441442
/// <returns>A random number from the specified normal distribution.</returns>
442443
/// <remarks>
443444
/// <para>
@@ -446,20 +447,24 @@ public static bool AlmostEqual<T>(T a, T b)
446447
/// </para>
447448
/// <para><b>For Beginners:</b> Normal distribution (also called Gaussian distribution) is a
448449
/// bell-shaped probability distribution that is symmetric around its mean.
449-
///
450+
///
450451
/// This method generates random numbers that follow this distribution, which is important for
451452
/// neural network initialization. Using normally distributed values helps prevent issues during
452453
/// training and improves convergence.
453454
/// </para>
455+
/// <para>
456+
/// For reproducible results, pass in a seeded Random instance. Otherwise, a new unseeded
457+
/// Random will be created on each call, which breaks reproducibility.
458+
/// </para>
454459
/// </remarks>
455-
public static T GetNormalRandom<T>(T mean, T stdDev)
460+
public static T GetNormalRandom<T>(T mean, T stdDev, Random? random = null)
456461
{
457462
var numOps = GetNumericOperations<T>();
458-
var random = new Random();
463+
var rng = random ?? new Random();
459464

460465
// Box-Muller transform
461-
double u1 = 1.0 - random.NextDouble(); // Uniform(0,1] random numbers
462-
double u2 = 1.0 - random.NextDouble();
466+
double u1 = 1.0 - rng.NextDouble(); // Uniform(0,1] random numbers
467+
double u2 = 1.0 - rng.NextDouble();
463468
double randStdNormal = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Sin(2.0 * Math.PI * u2);
464469

465470
// Scale and shift to get desired mean and standard deviation
@@ -638,7 +643,7 @@ private static T BesselJRecurrence<T>(T nu, T x)
638643
/// <remarks>
639644
/// <para>
640645
/// <b>For Beginners:</b> The factorial of a number (written as n!) is the product of all positive
641-
/// integers less than or equal to n. For example, 5! = 5 × 4 × 3 × 2 × 1 = 120.
646+
/// integers less than or equal to n. For example, 5! = 5 4 3 2 1 = 120.
642647
/// Factorials are used in many probability and statistics calculations.
643648
/// </para>
644649
/// </remarks>
@@ -747,7 +752,7 @@ public static T Tanh<T>(T x)
747752
/// <remarks>
748753
/// <para>
749754
/// <b>For Beginners:</b> The base-2 logarithm (log2) tells you what power you need to raise 2 to in order
750-
/// to get a specific number. For example, log2(8) = 3 because 2³ = 8. Base-2 logarithms are commonly
755+
/// to get a specific number. For example, log2(8) = 3 because 2 = 8. Base-2 logarithms are commonly
751756
/// used in computer science and information theory because computers use binary (base-2) number systems.
752757
/// </para>
753758
/// </remarks>
@@ -957,7 +962,7 @@ public static T Erf<T>(T x)
957962
/// before considering any features.
958963
/// </para>
959964
/// <para>
960-
/// This method uses the formula: y-intercept = mean(y) - (coefficient1 × mean(x1) + coefficient2 × mean(x2) + ...)
965+
/// This method uses the formula: y-intercept = mean(y) - (coefficient1 mean(x1) + coefficient2 mean(x2) + ...)
961966
/// which ensures that the regression line passes through the point of means (the average of all data points).
962967
/// </para>
963968
/// <para>

0 commit comments

Comments
 (0)