# L-40 MCS 260 Wed 20 Apr 2016 : multiprocess4pi.py
"""
Script to illustrate the application of the
multiprocessing module to apply Monte Carlo simulation
to compute an estimate for pi.
"""

from multiprocessing import Process, Queue
from math import pi

def monte_carlo4pi(nbr, nsd, result):
    """
    Estimates pi with nbr samples,
    using nsd as seed.
    Adds the result to the queue q.
    """
    from random import uniform as u
    from random import seed
    seed(nsd)
    cnt = 0
    for _ in range(nbr):
        (x, y) = (u(-1, 1), u(-1, 1))
        if x**2 + y**2 <= 1:
            cnt = cnt + 1
    result.put(cnt)

def main():
    """
    Prompts the user for the number of samples
    and the number of processes.
    """
    nbr = int(input('Give the number of samples : '))
    npr = int(input('Give the number of processes : '))
    queues = [Queue() for _ in range(npr)]
    procs = []
    for k in range(1, npr+1):
        procs.append(Process(target=monte_carlo4pi, \
            args=(nbr, k, queues[k-1])))
    for process in procs:
        process.start()
    for process in procs:
        process.join()
    app = 4*sum([q.get()/nbr for q in queues])/npr
    print(app, 'error : %.3e' % abs(app - pi))

main()
