Knowledge Guide
HomeConcurrencyConcurrency Problems

Problem 5 Pi calculation

Overview

The problem is to estimate the value of Pi using a Monte Carlo simulation method. In this method, we randomly generate points within a square and check how many of these points fall inside a circle inscribed within the square. The ratio of points inside the circle to the total points generated provides an approximation of Pi.

Multithreading Solution

To speed up the Monte Carlo simulation and make efficient use of multiple CPU cores, multithreading is employed. Here's how it works:

  1. Dividing the Work: The total number of points to be generated (SIZE) is divided into smaller chunks, with each chunk assigned to a different thread. In this case, there are NUM_THREADS threads, so each thread handles SIZE / NUM_THREADS points.
  2. Independent Simulations: Each thread performs an independent Monte Carlo simulation, generating its set of random points within the square. Since each thread uses a different seed for randomness (based on thread ID and time), the points generated by each thread are distinct.
  3. Counting Points in the Circle: For each generated point, the thread checks if it falls within the inscribed circle (based on the distance from the origin). If a point is inside the circle, the thread increments its own counter (count_in_circle) to keep track of how many points it generated that landed inside the circle.
  4. Aggregating Results: After all threads have completed their simulations, the count of points inside the circle (count_in_circle) for each thread is collected and stored in the results array.
  5. Final Estimation: The results from all threads are summed up to get the total number of points inside the circle (total_inside). This total is used to estimate Pi by multiplying it by 4 and dividing by the total number of generated points (SIZE).
  6. Output: The estimated value of Pi is printed to the console.

Multithreading allows for the concurrent execution of simulations, significantly speeding up the Monte Carlo estimation of Pi by utilizing the capabilities of multi-core processors. Each thread works independently on a portion of the problem, and their results are combined to obtain the final estimation.

Pseudocode

Define: SIZE as the total number of points to generate NUM_THREADS as the number of threads to use results[NUM_THREADS] as an array to store results from each thread Function monte_carlo_pi(threadid): tid = threadid start = tid * (SIZE / NUM_THREADS) end = (tid + 1) * (SIZE / NUM_THREADS) count_in_circle = 0 Initialize random number generator with seed based on tid For i from start to end: Generate random x and y coordinates between -1 and 1 If (x^2 + y^2) <= 1: Increment count_in_circle Store count_in_circle in results[tid] Create an array of threads with size NUM_THREADS For i from 0 to NUM_THREADS-1: Create a thread and assign it the function monte_carlo_pi with thread ID i For i from 0 to NUM_THREADS-1: Wait for thread[i] to finish total_inside = 0 For i from 0 to NUM_THREADS-1: Add results[i] to total_inside pi_estimate = 4.0 * total_inside / SIZE Print "Estimated Pi = " + pi_estimate

Algorithm Walkthrough

Let's break down the pseudocode step-by-step using a dry run with small values for clarity:

Suppose:

Initialization

  1. We have SIZE as 100, which represents the total number of random points we'll generate.
  2. We decide to use NUM_THREADS which is 2, implying we're splitting our workload into 2 threads.
  3. We initialize an array results[2] to store the results from each thread. Let's assume results = [0, 0].

Function monte_carlo_pi(threadid)

Main Execution

  1. Create an array of threads of size 2.
  2. For i from 0 to 1:
    • A thread is created and assigned the function monte_carlo_pi with thread ID i.
  3. Again, for i from 0 to 1:
    • We wait for each thread to finish its execution.
  4. total_inside is initialized to 0.
  5. For i from 0 to 1:
    • The value of results[i] is added to total_inside.
  6. pi_estimate is calculated as 4.0 * total_inside / 100.
  7. The estimated value of π is printed.

Example For the sake of simplicity, let's assume:

Then, total_inside = 40 + 35 = 75. The estimate of π would be pi_estimate = 4.0 * 75/100 = 3.0 (This is just an illustrative value and might not represent an accurate estimation of π.)

Image
Image
Image
Image
Image
Image
Image
Image
java
import java.util.Random;

public class Solution {

  private static final int NUM_THREADS = 4;
  private static final int NUMBER_OF_TOSSES = 1000000;
  private static int[] results = new int[NUM_THREADS];

  public static void main(String[] args) throws InterruptedException {
    Thread[] threads = new Thread[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++) {
      final int threadId = i;
      threads[i] = new Thread(() -> {
        Random rand = new Random();
        int start = (threadId * NUMBER_OF_TOSSES) / NUM_THREADS;
        int end = ((threadId + 1) * NUMBER_OF_TOSSES) / NUM_THREADS;
        int count_in_circle = 0;

        for (int j = start; j < end; j++) {
          double x = rand.nextDouble() * 2 - 1; // Random x in range [-1, 1]
          double y = rand.nextDouble() * 2 - 1; // Random y in range [-1, 1]
          if (x * x + y * y <= 1) { // If point is inside the circle
            count_in_circle++;
          }
        }
        results[threadId] = count_in_circle;
      });
      threads[i].start();
    }

    for (Thread thread : threads) {
      thread.join();
    }

    // Compute final estimate of Pi
    int total_inside = 0;
    for (int result : results) {
      total_inside += result;
    }
    double pi_estimate = (4.0 * total_inside) / NUMBER_OF_TOSSES;
    System.out.println("PI = " + pi_estimate);
  }
}
🤖 Don't fully get this? Learn it with Claude

Stuck on Problem 5 Pi calculation? Open Claude, copy a block below, and it'll teach you this exact concept — visually and interactively.

🪜 Hint ladder (no spoilers)

Progressively stronger hints — you still solve it.

I'm working on the problem **Problem 5 Pi calculation** (Concurrency). Give me a HINT LADDER: start with the tiniest nudge, then wait. Only reveal the next, stronger hint when I ask. Do NOT show the full solution unless I type 'show solution'. Keep me doing the thinking. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🎨 Explain the approach visually

See the technique, not just code.

Explain the optimal approach to **Problem 5 Pi calculation** with a VISUAL walkthrough: trace it on a small concrete example using ASCII art / a step-by-step diagram, narrate what changes each step, then give time & space complexity with a one-line derivation. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔍 Review my solution

Catch bugs, edge cases, sub-optimality.

I'll paste my solution to **Problem 5 Pi calculation**. Review it for correctness, missed edge cases, and time/space complexity, then coach me toward the optimal — don't just rewrite it. Ask me to paste my code now. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.
🔁 Drill the pattern

Lock in recognition with look-alikes.

Give me 2 problems that use the SAME underlying pattern as **Problem 5 Pi calculation**. For each, let me attempt first, then review my answer and name the trigger signal that reveals the pattern. If you're unsure or a claim isn't standard, say so and reason from first principles instead of guessing.

📝 My notes