C# Coding Projects

Project #1: Exploring Numerical Integration and Differentiation in C#

Numerical methods are the backbone of solving real-world computational problems, and implementing them in a programming language is an excellent way to solidify one’s understanding of both the mathematics and the coding concepts involved. I undertook a project in my C# programming course that focused on numerical integration and differentiation techniques, showcasing the language’s capabilities for handling mathematical computations and reinforcing my knowledge of numerical analysis.

Project Overview

This project involved developing three key methods for numerical calculus:

1. Rectangular Method for Integration: An approach to approximate definite integrals by summing up areas of rectangles under a curve.

public double RectangularMethod(Func<double, double> function, double a, double b, int n)
{
    double width = (b - a) / n;
    double sum = 0;

    for (int i = 0; i < n; i++)
    {
        double x = a + i * width;
        sum += function(x);
    }

    return sum * width;
}

2. Adaptive Rectangular Method: An enhancement of the basic rectangular method, dynamically adjusting the rectangle width to improve accuracy, especially for polynomial and simple trigonometric functions.

public double AdaptiveRectangularMethod(Func<double, double> function, double a, double b, double tolerance)
{
    double currentArea = RectangularMethod(function, a, b, 100);
    double refinedArea;
    int n = 200;

    do
    {
        refinedArea = RectangularMethod(function, a, b, n);
        if (Math.Abs(refinedArea - currentArea) <= tolerance)
            break;

        currentArea = refinedArea;
        n *= 2;
    } while (n <= 1_000_000);

    return refinedArea;
}

3. Improved Central Difference Method for Differentiation: A method to estimate derivatives with greater precision by considering values on both sides of the point of interest.

public double CentralDifference(Func<double, double> function, double x, double h)
{
    return (function(x + h) - function(x - h)) / (2 * h);
}

These methods were implemented with a focus on clean, readable code and comprehensive testing to ensure accuracy and reliability.

Implementation Details

The project adhered to specific design constraints to promote good programming practices:

Modular Design: Each numerical method was encapsulated in its respective function, making the code easier to maintain and reuse.

public double Evaluate(Func<double, double> function, double a, double b, string method, double tolerance = 0.001)
{
    return method switch
    {
        "rectangular" => RectangularMethod(function, a, b, 100),
        "adaptive" => AdaptiveRectangularMethod(function, a, b, tolerance),
        _ => throw new ArgumentException("Invalid method")
    };
}

Use of Helper Methods: Local functions were employed to break down the computations into smaller, manageable tasks, improving readability and debugging.

private double TrapezoidalSegment(Func<double, double> function, double x1, double x2)
{
    return 0.5 * (function(x1) + function(x2)) * (x2 - x1);
}

Testing and Validation: A comprehensive suite of unit tests was developed to validate the methods, using a range of polynomial and trigonometric test cases.

[TestMethod]
public void TestCentralDifference()
{
    Func<double, double> function = x => x * x;
    double derivative = CentralDifference(function, 2.0, 0.001);
    Assert.AreEqual(4.0, derivative, 0.001);
}

Program Menu:

The calculator program included an interactive menu for setting polynomials, evaluating its derivatives and integrals at x values, getting its roots, printing the polynomial, and evaluating arithmetic expressions. Users can interact with the calculator through the console on Visual Studios.

Challenges and Learnings

One of the challenges was balancing precision and computational efficiency, particularly in the adaptive rectangular method. This required thoughtful decisions about step sizes and tolerances to ensure accurate results without excessive computation. Through this project, I gained a deeper understanding of numerical methods and the power of C# as a tool for implementing mathematical algorithms. The exercise also honed my problem-solving skills and reinforced the importance of writing clear, maintainable code.

Project #2: Simulating Percolation with Monte Carlo Methods (Collaborative Project)

This group project combined the power of computational simulations with collaborative development. The assignment focused on implementing a simulation to calculate the probability of percolation in grids using Monte Carlo methods, providing hands-on experience in C# programming, teamwork, and version control with GitHub.

Project Objective

The project aimed to simulate and analyze percolation—a phenomenon where open cells in a grid form continuous paths—and estimate the probability of percolation based on a vacancy probability. Key deliverables included:

1. Implementation of Core Classes and Methods:

SimulatorMain.cs: Handled the main program logic and user interaction.I developed the interactive menu system, which allows users to configure grid parameters, visualize grids, and perform simulations. A sample from the implementation:

while (true)
{
    Console.WriteLine("Select from this menu:");
    Console.WriteLine("Grid parameters: di(m)ension, (v)acancy probability, (n)um of trials, (g)et parameters");
    Console.WriteLine("Single grid: (c)reate a grid, (d)isplay, (p)ercolate");
    Console.WriteLine("Monte Carlo: start Mon(t)e Carlo simulation");
    Console.WriteLine("Quit: (q)uit");
    Console.Write("\nYour choice: ");
    string choice = Console.ReadLine().Trim().ToLower();

    if (choice.StartsWith("q"))
    {
        Console.WriteLine("exit");
        break;
    }
    // Additional menu options implemented here...
}

MonteCarlo.cs: Implemented the Monte Carlo simulation to estimate percolation probability. The implementation of the Estimate method can be seen below:

public static double Estimate(int dimension, double probability, int numOfTrials)
{
    int countPercolate = 0;

    for(int i = 0; i < numOfTrials; i++)
    {
        bool[,] grid = RandomGridGenerator.Generate(dimension, probability);
        bool trial = Percolation.IsPercolating(grid);

        if(trial)
        {
            countPercolate++;
        }
    }

    double estimate = (double)countPercolate / numOfTrials;
    return estimate;
}

Percolation.cs: Included methods to determine if a grid percolates and to calculate intermediary grids. I worked extensively on the Infiltrate method, ensuring efficient recursion:

public static bool[,] Infiltrate(bool[,] grid)
{
    int dimension = grid.GetLength(0);
    bool[,] outputGrid = new bool[dimension, dimension];
    Queue<int[]> tiles = new Queue<int[]>();

    for (int i = 0; i < dimension; i++)
    {
        if (grid[0, i])
        {
            tiles.Enqueue(new int[] { 0, i });
            InfiltrateRecursion(tiles, grid, outputGrid, dimension);
        }
    }

    return outputGrid;
}

2. Unit Testing:

Thoroughly tested methods in MonteCarlo.cs and Percolation.cs to ensure robust and accurate code. For example, I wrote the following test to validate the Estimate method:

[TestMethod]
public void EstimateTestAllVacancy()
{
    for (int i = 3; i <= 50; i++)
    {
        Assert.AreEqual(MonteCarloSimulation.Estimate(i, 1, 100), 1, 0.00000001);
    }
}

3. UML Diagram:

Created a class diagram visually detailing the project’s structure:

4. Version Control:

Regularly contributed to a GitHub repository to demonstrate individual and group progress and work collaboratively as a team.

Technical Highlights

Monte Carlo Simulation:

This statistical method involved generating multiple random grids with a specified vacancy probability, determining whether each grid percolated, and calculating the percolation probability as the fraction of grids that percolated. One challenge was ensuring accurate results for varying grid sizes and probabilities. I addressed this by running multiple trials and averaging the results:

double probability = 0;
for (int i = 0; i < 10; i++)
{
    probability += MonteCarloSimulation.Estimate(3, 0.593, 50000);
}
probability /= 10;
Assert.AreEqual(0.56, probability, 0.01);

Percolation Detection:

The IsPercolating method used the Infiltrate method to identify open paths from the top to the bottom of the grid. The infiltration method employed recursion to mark connected open cells. I handled edge cases like disconnected grids effectively:

[TestMethod]
public void IsPercolatingTestBlockedGrid()
{
    bool[,] grid = new bool[,]
    {
        { true, false, true },
        { false, false, false },
        { true, false, true }
    };

    Assert.IsFalse(Percolation.IsPercolating(grid), "Grid with no connected path should not percolate.");
}

Program Menu:

The simulator included an interactive menu for configuring grid parameters, running simulations, and visualizing results. Users can interact with the simulation through the console on Visual Studios.

Collaboration and Tools

Group Coordination:

Regular meetings and task assignments ensured balanced contributions. Clear milestones helped the team maintain momentum and adapt to challenges. My role included spearheading discussions on debugging strategies and ensuring the integration of various components.

GitHub Workflow:

Each group member pushed incremental commits to the shared repository, showcasing individual contributions and collaboration. I resolved several merge conflicts efficiently and maintained a clean commit history.

Challenges and Solutions

Recursive Algorithms:

Implementing the Infiltrate method required careful handling of recursion to avoid infinite loops and ensure efficiency. Debugging recursive calls with complex grids was a key learning experience.

Error Handling:

The program’s input/output interactions included robust error handling, providing clear feedback to the user for invalid inputs.

Collaboration Tools:

Using GitHub efficiently required learning advanced features like branching and resolving merge conflicts, enhancing the team’s version control skills.

Key Takeaways

The Simulating Percolation with Monte Carlo Methods project offered valuable experience with breaking down complex problems, maintaining effective teamwork, and refining technical skills. It highlighted the importance of clear communication, robust program testing, and iterative development, ensuring a successful and organized outcome. The final submission showcased a comprehensive simulation program, rigorous testing, and an organized codebase.

Leave a comment