LinearRegression

Date: 2023-11-06
namespace Domain.Helpers
{
    public struct Point2D {
        public double X;
        public double Y;
    }

    public class LinearRegression
    {
        public static void Example()
        {
            // Voorbeeldwaarden
            double slope = 1.4;    // Helling
            double intercept = 3.5; // Startpositie (intercept)
            double x = 2.0;        // x-coördinaat van het punt dat je wilt berekenen

            // Gebruik CalculateY om het y-coördinaat te berekenen
            double y = CalculateY(slope, intercept, x);

            // Toon het berekende punt
            Console.WriteLine($"Voor x = {x}, y = {y}");
            // Voor x = 2, y = 6.3
        }

        public static double CalculateY(double slope, double intercept, double x) => slope * x + intercept;

        public static double Slope(IEnumerable<Point2D> points)
        {
            if (!ValidInput(points)) return 0.0;

            var x = points.Select(point => point.X).ToArray();
            var y = points.Select(point => point.Y).ToArray();

            return Correlation(x, y) / SumOfSquares(x);
        }

        public static double Intercept(IEnumerable<Point2D> points)
        {
            if (!ValidInput(points)) return 0.0;

            var x = points.Select(point => point.X).ToArray();
            var y = points.Select(point => point.Y).ToArray();

            var xAverage = Average(x);
            var yAverage = Average(y);

            return yAverage - Slope(points) * xAverage;
        }

        public static double Average(double[] values)
        {
            if (!ValidInput(values)) return 0.0;
            return values.Average();
        }

        public static double SumOfSquares(double[] values)
        {
            if (!ValidInput(values)) return 0.0;
            var sumOfSquares = values.Select(v => v * v).Sum();
            var average = Average(values);
            sumOfSquares -= average * average * values.Length;
            return sumOfSquares;
        }

        public static double Correlation(double[] x, double[] y)
        {
            if (!ValidInput(x, y)) return 0.0;
            var correlation = 0.0;
            for (int i = 0; i < x.Length; ++i)
                correlation += x[i] * y[i];
            var xAverage = Average(x);
            var yAverage = Average(y);
            correlation -= xAverage * yAverage * x.Length;
            return correlation;
        }

        private static bool ValidInput(double[] x, double[] y) => x != null && y != null && x.Length == y.Length && x.Length != 0;
        private static bool ValidInput(double[] x) => x != null && x.Length != 0;
        private static bool ValidInput(IEnumerable<Point2D> points) => points != null && points.Any();
    }
}
using Domain.Helpers;
using NUnit.Framework;

namespace Domain.Tests
{
    [TestFixture]
    public class LinearRegressionTests
    {
        public const double Tolerance = 1.0e-6;

        [Test]
        public void TestAverage_NullArray()
        {
            // setup
            double[] x = null;
            double expected = 0.0;
            // exercise
            double actual = LinearRegression.Average(x);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestAverage_EmptyArray()
        {
            // setup
            double[] x = new double[] { };
            double expected = 0.0;
            // exercise
            double actual = LinearRegression.Average(x);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestAverage_Success()
        {
            // setup
            double[] x = new double[] { 1.0, 2.0, 2.0, 3.0, 4.0, 7.0, 9.0 };
            double expected = 4.0;
            // exercise
            double actual = LinearRegression.Average(x);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestSumOfSquares_NullArray()
        {
            // setup
            double[] x = null;
            double expected = 0.0;
            // exercise
            double actual = LinearRegression.SumOfSquares(x);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestSumOfSquares_EmptyArray()
        {
            // setup
            double[] x = new double[] { };
            double expected = 0.0;
            // exercise
            double actual = LinearRegression.SumOfSquares(x);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestSumOfSquares_Success()
        {
            // setup
            double[] x = new double[] { 1.0, 2.0, 2.0, 3.0, 4.0, 7.0, 9.0 };
            double expected = 52.0;
            // exercise
            double actual = LinearRegression.SumOfSquares(x);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestCorrelation_NullX_NullY()
        {
            // setup
            double[] x = null;
            double[] y = null;
            double expected = 0.0;
            // exercise
            double actual = LinearRegression.Correlation(x, y);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestCorrelation_DifferentLengths()
        {
            // setup
            double[] x = new double[] { 1.0, 2.0, 3.0, 5.0, 8.0 };
            double[] y = new double[] { 0.11, 0.12, 0.13, 0.15, 0.18, 0.20 };
            double expected = 0.0;
            // exercise
            double actual = LinearRegression.Correlation(x, y);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestCorrelation_Success()
        {
            // setup
            double[] x = new double[] { 1.0, 2.0, 3.0, 5.0, 8.0 };
            double[] y = new double[] { 0.11, 0.12, 0.13, 0.15, 0.18 };
            double expected = 0.308;
            // exercise
            double actual = LinearRegression.Correlation(x, y);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestSlope()
        {
            // setup
            var points = new List<Point2D> {
                new Point2D { X = 1.0, Y = 6.0 },
                new Point2D { X = 2.0, Y = 5.0 },
                new Point2D { X = 3.0, Y = 7.0 },
                new Point2D { X = 4.0, Y = 10.0 }
                };
            double expected = 1.4;
            // exercise
            double actual = LinearRegression.Slope(points);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }

        [Test]
        public void TestIntercept()
        {
            var points = new List<Point2D> {
                new Point2D { X = 1.0, Y = 6.0 },
                new Point2D { X = 2.0, Y = 5.0 },
                new Point2D { X = 3.0, Y = 7.0 },
                new Point2D { X = 4.0, Y = 10.0 }
                };

            double expected = 3.5;
            // exercise
            double actual = LinearRegression.Intercept(points);
            // assert
            Assert.That(actual, Is.EqualTo(expected).Within(Tolerance));
        }
    }
}
80940cookie-checkLinearRegression