Esempio n. 1
0
def main():
    fcns = {
        'preprocess': example_preprocess,
        'run': example_run,
        'postprocess': example_postprocess
    }

    ndraws = 1024
    seed = 123456  # Recommended for repeatability

    # Initialize the simulation
    sim = mc.Sim(name='Dice Roll',
                 singlethreaded=True,
                 savecasedata=False,
                 ndraws=ndraws,
                 fcns=fcns,
                 seed=seed)

    # Generate the input variables
    sim.addInVar(name='die1',
                 dist=randint,
                 distkwargs={
                     'low': 1,
                     'high': 6 + 1
                 })
    sim.addInVar(name='die2',
                 dist=randint,
                 distkwargs={
                     'low': 1,
                     'high': 12 + 1
                 })

    # Run the Simulation
    sim.runSim()

    # Calculate the mean and 5-95th percentile statistics for the dice sum
    sim.outvars['Sum'].addVarStat('mean')
    sim.outvars['Sum'].addVarStat('percentile', {'p': [0.95, 0.05]})

    # Plots a histogram of the dice sum
    fig, axs = plt.subplots(3, 1)
    mc.plot(sim.outvars['Sum'], plotkwargs={'bins': 16}, ax=axs[0])

    # Creates a scatter plot of the dum vs the roll number, showing randomness
    mc.plot(sim.outvars['Sum'], sim.outvars['Roll Number'], ax=axs[1])
    axs[1].get_shared_x_axes().join(axs[0], axs[1])

    # Calculate the sensitivity of the dice sum to each of the input variables
    sim.calcSensitivities('Sum')
    sim.outvars['Sum'].plotSensitivities(ax=axs[2])

    plt.show(block=True)
Esempio n. 2
0
def pandemic_example_monte_carlo_sim():

    sim = mc.Sim(name='pandemic',
                 ndraws=ndraws,
                 fcns=fcns,
                 firstcaseismedian=True,
                 seed=seed,
                 singlethreaded=False,
                 verbose=True,
                 debug=False)

    sim.addInVar(name='Probability of Infection',
                 dist=uniform,
                 distkwargs={
                     'loc': 0.28,
                     'scale': 0.04
                 })

    sim.runSim()

    sim.outvars['Proportion Infected'].addVarStat(stat='orderstatTI',
                                                  statkwargs={
                                                      'p': p,
                                                      'c': c,
                                                      'bound': bound
                                                  })
    sim.outvars['Superspreader Degree'].addVarStat(stat='orderstatTI',
                                                   statkwargs={
                                                       'p': 0.5,
                                                       'c': 0.5,
                                                       'bound': 'all'
                                                   })

    mc.plot(sim.outvars['Timestep'], sim.outvars['Superspreader Degree'])
    mc.plot(sim.outvars['Max Superspreader Degree'], highlight_cases=0)
    mc.plot(sim.outvars['Herd Immunity Threshold'], highlight_cases=0)
    '''
    import matplotlib.pyplot as plt
    fig, ax = mc.plot(sim.outvars['Timestep'], sim.outvars['Proportion Infected'],
                      highlight_cases=0)
    fig.set_size_inches(8.8, 6.0)
    plt.savefig('cum_infections_vs_time.png', dpi=100)

    fig, axs = mc.multi_plot([sim.invars['Probability of Infection'],
                              sim.outvars['Herd Immunity Threshold']],
                             cov_plot=False, highlight_cases=0)
    fig.set_size_inches(8.8, 6.0)
    plt.savefig('p_infection_vs_herd_immunity.png', dpi=100)
    #'''

    return sim
Esempio n. 3
0
def test_calc_sensitivities():
    fcns = {
        'preprocess': vars_preprocess,
        'run': vars_run,
        'postprocess': vars_postprocess
    }

    ndraws = 128
    sim = mc.Sim(name='dvars',
                 ndraws=ndraws,
                 fcns=fcns,
                 firstcaseismedian=False,
                 seed=3462356,
                 singlethreaded=True,
                 daskkwargs=dict(),
                 samplemethod='random',
                 savecasedata=False,
                 savesimdata=False,
                 verbose=False,
                 debug=True)

    varnames = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6']
    for varname in varnames:
        sim.addInVar(name=varname,
                     dist=uniform,
                     distkwargs={
                         'loc': 0,
                         'scale': 1
                     })
    sim.runSim()

    sim.calcSensitivities('f')
    # sim.outvars['f'].plotSensitivities()

    calculated_ratios = list(sim.outvars['f'].sensitivity_ratios.values())
    expected_ratios = [
        0.471030, 0.361213, 0.062541, 0.074203, 0.030412, 0.000598
    ]
    assert np.allclose(calculated_ratios, expected_ratios, atol=1e-6)
def election_example_monte_carlo_sim():
    sim = mc.Sim(name='election',
                 ndraws=ndraws,
                 fcns=fcns,
                 firstcaseismedian=False,
                 seed=seed,
                 singlethreaded=True,
                 samplemethod='random',
                 savecasedata=False,
                 verbose=True,
                 debug=False)

    rootdir = pathlib.Path(__file__).parent.absolute()
    df = pd.read_csv(rootdir / 'state_presidential_odds.csv')
    states = df['State'].tolist()
    df['Dem_Sig'] = df['Dem_80_tol'] / mc.pct2sig(0.8, bound='2-sided')
    df['Rep_Sig'] = df['Rep_80_tol'] / mc.pct2sig(0.8, bound='2-sided')
    df['Other_Sig'] = df['Other_80_tol'] / mc.pct2sig(0.8, bound='2-sided')

    sim.addInVar(name='National Dem Swing',
                 dist=uniform,
                 distkwargs={
                     'loc': -0.03,
                     'scale': 0.06
                 })

    for state in states:
        i = df.loc[df['State'] == state].index[0]
        sim.addInVar(name=f'{state} Dem Unscaled Pct',
                     dist=norm,
                     distkwargs={
                         'loc': df['Dem_Mean'][i],
                         'scale': df['Dem_Sig'][i]
                     })
        sim.addInVar(name=f'{state} Rep Unscaled Pct',
                     dist=norm,
                     distkwargs={
                         'loc': df['Rep_Mean'][i],
                         'scale': df['Rep_Sig'][i]
                     })
        sim.addInVar(name=f'{state} Other Unscaled Pct',
                     dist=norm,
                     distkwargs={
                         'loc': df['Other_Mean'][i],
                         'scale': df['Other_Sig'][i]
                     })

    sim.addConstVal(name='states', val=states)
    sim.addConstVal(name='df', val=df)

    sim.runSim()

    sim.outvars['Dem EVs'].addVarStat(stat='orderstatP',
                                      statkwargs={
                                          'p': 0.5,
                                          'bound': 'nearest'
                                      })
    sim.outvars['Dem EVs'].addVarStat(stat='orderstatTI',
                                      statkwargs={
                                          'p': 0.75,
                                          'c': 0.90,
                                          'bound': '2-sided'
                                      })
    fig, ax = mc.plot(sim.outvars['Dem EVs'], plotkwargs={'bins': 50})
    ax.set_autoscale_on(False)
    ax.plot([270, 270], [0, 1], '--k')
    fig.set_size_inches(8.0, 4.5)
    plt.savefig('ev_histogram.png', dpi=100)

    pct_dem_win = sum(x == 'Dem'
                      for x in sim.outvars['Winner'].vals) / sim.ncases
    pct_rep_win = sum(x == 'Rep'
                      for x in sim.outvars['Winner'].vals) / sim.ncases
    pct_contested = sum(x == 'Contested'
                        for x in sim.outvars['Winner'].vals) / sim.ncases
    print(f'Win probabilities: {100*pct_dem_win:0.1f}% Dem, ' +
          f'{100*pct_rep_win:0.1f}% Rep, ' +
          f'{100*pct_contested:0.1f}% Contested')
    mc.plot(sim.outvars['Winner'])

    pct_recount = sum(x != 0
                      for x in sim.outvars['Num Recounts'].vals) / sim.ncases
    print(
        f'In {100*pct_recount:0.1f}% of runs there was a state close enough ' +
        'to trigger a recount (<0.5%)')

    dem_win_state_pct = dict()
    for state in states:
        dem_win_state_pct[state] \
            = sum(x == 'Dem' for x in sim.outvars[f'{state} Winner'].vals)/sim.ncases

    # Only generate state map if plotly installed. Want to avoid this as a dependency
    gen_map = False
    import importlib
    if importlib.util.find_spec('plotly') and gen_map:
        import plotly.graph_objects as go
        from plotly.offline import plot
        plt.figure()
        fig = go.Figure(data=go.Choropleth(
            locations=df['State_Code'],  # Spatial coordinates
            z=np.fromiter(dem_win_state_pct.values(), dtype=float) * 100,
            locationmode='USA-states',
            colorscale='RdBu',
            colorbar_title="Dem % Win"))

        fig.update_layout(geo_scope='usa')
        plot(fig)

    return sim
def template_monte_carlo_sim():
    # We first initialize the sim with a name of our choosing
    sim = mc.Sim(name='Coin Flip',
                 ndraws=ndraws,
                 fcns=fcns,
                 firstcaseismedian=firstcaseismedian,
                 seed=seed,
                 singlethreaded=singlethreaded,
                 savecasedata=savecasedata,
                 savesimdata=savesimdata,
                 verbose=True,
                 debug=False)

    # We now add input variables, with their associated distributions
    # Out first variable will be the person flipping a coin - Sam and Alex will
    # do so with even odds.
    # For even odds between 0 and 1 we want to call scipy.stats.randint(0,2)
    # The dist argument is therefor randint, and we look up its arguments in the
    # documentation:
    # https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.randint.html
    # The kwargs are {'low':0, 'high':2}, which we package in a keyword dictionary.
    # Since our inputs here are strings rather than numbers, we need to map the
    # numbers from our random draws to those imputs with a nummap dictionary
    nummap = {0: 'Sam', 1: 'Alex'}
    sim.addInVar(name='flipper',
                 dist=randint,
                 distkwargs={
                     'low': 0,
                     'high': 2
                 },
                 nummap=nummap)

    # If we want to generate custom odds, we can create our own distribution, see:
    # https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.rv_discrete.html
    # Let's assume that we have a weighted coin where heads comes up 70% of the time.
    # Our 'template_run' run function reads 0 as heads and 1 as tails.
    flip_dist = rv_discrete(name='flip_dist', values=([0, 1], [0.7, 0.3]))
    # If the distribution is custom then it doesn't take arguments, so pass in
    # an empty dictionary
    sim.addInVar(name='flip', dist=flip_dist, distkwargs=dict())

    # Once all input variables are initialized, we run the sim.
    # For each case, the preprocessing function will pull in the random variables
    # and any other data the run fuction needs, the run function executes, and
    # its output is passed to the postprocessing function for extracting the
    # desired output values from each case.
    # The cases are collected, and the individual output values are collected into
    # an output variable stored by the sim object.
    sim.runSim()

    # Once the sim is run, we have access to its member variables.
    print(f'{sim.name} Runtime: {sim.runtime}')

    # From here we can perform further postprocessing on our results. The outvar
    # names were assigned in our postprocessing function. We expect the heads
    # bias to be near the 70% we assigned up in flip_dist.
    bias = sim.outvars['Flip Result'].vals.count('heads') / sim.ncases * 100
    print(f'Average heads bias: {bias}%')

    # We can also quickly make some plots of our invars and outvars. The mc.plot
    # function will automatically try to figure out which type of plot is most
    # appropriate based on the number and dimension of the variables.
    # This will make a histogram of the results:
    mc.plot(sim.outvars['Flip Result'])
    # And this scatter plot will show that the flips were random over time:
    mc.plot(sim.outvars['Flip Number'], sim.outvars['Flip Result'])

    # We can also look at the correlation between all scalar input and output
    # vars to see which are most affecting the others. This shows that the input
    # and output flip information is identical, and that the flipper and flip
    # number had no effect on the coin landing heads or tails.
    mc.plot_cov_corr(*sim.corr())

    # Alternatively, you can return the sim object and work with it elsewhere.
    return sim
Esempio n. 6
0
def integration_example_monte_carlo_sim():

    sim = mc.Sim(name='integration',
                 ndraws=ndraws,
                 fcns=fcns,
                 firstcaseismedian=firstcaseismedian,
                 samplemethod=samplemethod,
                 seed=seed,
                 singlethreaded=True,
                 savecasedata=savecasedata,
                 savesimdata=False,
                 verbose=True,
                 debug=True)

    sim.addInVar(name='x',
                 dist=uniform,
                 distkwargs={
                     'loc': xrange[0],
                     'scale': (xrange[1] - xrange[0])
                 })  # -1 <= x <= 1
    sim.addInVar(name='y',
                 dist=uniform,
                 distkwargs={
                     'loc': yrange[0],
                     'scale': (yrange[1] - yrange[0])
                 })  # -1 <= y <= 1

    sim.runSim()

    # Note that (True,False) vals are automatically valmapped to the nums (1,0)
    underCurvePct = sum(sim.outvars['pi_est'].nums) / ndraws
    err = mc.integration_error(sim.outvars['pi_est'].nums,
                               dimension=dimension,
                               volume=totalArea,
                               conf=conf,
                               samplemethod=samplemethod,
                               runningerror=False)
    stdev = np.std(sim.outvars['pi_est'].nums, ddof=1)

    resultsstr = f'π ≈ {underCurvePct*totalArea:0.5f}, n = {ndraws}, ' + \
                 f'{round(conf*100, 2)}% error = ±{err:0.5f}, stdev={stdev:0.3f}'
    print(resultsstr)
    '''
    import matplotlib.pyplot as plt
    indices_under_curve = [i for i, x in enumerate(sim.outvars['pi_est'].vals) if x]
    fig, ax = mc.plot(sim.invars['x'], sim.invars['y'], highlight_cases=indices_under_curve)
    ax.axis('equal')
    plt.title(resultsstr)
    fig.set_size_inches(8.8, 6.0)
    plt.savefig('circle_integration.png', dpi=100)

    fig, ax = mc.plot_integration_convergence(sim.outvars['pi_est'], dimension=dimension,
                                              volume=totalArea, refval=np.pi, conf=0.95,
                                              title='Approx. value of π',
                                              samplemethod=samplemethod)
    ax.set_ylim((3.10, 3.18))
    fig.set_size_inches(8.8, 6.0)
    plt.savefig('pi_convergence.png', dpi=100)

    fig, ax = mc.plot_integration_error(sim.outvars['pi_est'], dimension=dimension,
                                        volume=totalArea, refval=np.pi, conf=0.95,
                                        title='Approx. error of π', samplemethod=samplemethod)
    fig.set_size_inches(8.8, 6.0)
    plt.savefig('pi_error.png', dpi=100)

    plt.show()
    #'''

    return sim
def baseball_example_monte_carlo_sim():
    ## Define sim
    sim = mc.Sim(name='baseball',
                 ndraws=ndraws,
                 fcns=fcns,
                 firstcaseismedian=True,
                 seed=seed,
                 singlethreaded=True,
                 verbose=True,
                 debug=True,
                 savecasedata=False,
                 savesimdata=False)

    ## Define input variables
    sim.addInVar(name='Y Init [m]',
                 dist=uniform,
                 distkwargs={
                     'loc': -19.94 * in2m / 2,
                     'scale': 19.94 * in2m
                 })
    sim.addInVar(name='Z Init [m]',
                 dist=uniform,
                 distkwargs={
                     'loc': 18.29 * in2m,
                     'scale': 25.79 * in2m
                 })
    sim.addInVar(name='Speed Init [m/s]',
                 dist=norm,
                 distkwargs={
                     'loc': 90 * mph2mps,
                     'scale': 5 * mph2mps
                 })
    sim.addInVar(name='Launch Angle [deg]',
                 dist=norm,
                 distkwargs={
                     'loc': 10,
                     'scale': 20
                 })
    sim.addInVar(name='Side Angle [deg]',
                 dist=norm,
                 distkwargs={
                     'loc': 0,
                     'scale': 30
                 })
    sim.addInVar(name='Topspin [rpm]',
                 dist=norm,
                 distkwargs={
                     'loc': 80,
                     'scale': 500
                 })
    sim.addInVar(name='Mass [kg]',
                 dist=uniform,
                 distkwargs={
                     'loc': 0.142,
                     'scale': 0.007
                 })
    sim.addInVar(name='Diameter [m]',
                 dist=uniform,
                 distkwargs={
                     'loc': 0.073,
                     'scale': 0.003
                 })
    sim.addInVar(name='Wind Speed [m/s]',
                 dist=uniform,
                 distkwargs={
                     'loc': 0,
                     'scale': 10
                 })
    sim.addInVar(name='Wind Azi [deg]',
                 dist=uniform,
                 distkwargs={
                     'loc': 0,
                     'scale': 360
                 })
    sim.addInVar(name='CD',
                 dist=norm,
                 distkwargs={
                     'loc': 0.300,
                     'scale': 0.015
                 })

    ## Run sim
    sim.runSim()

    ## Generate stats and plots
    homerun_indices = np.where(sim.outvars['Home Run'].vals)[0]
    # foul_indices = np.where(sim.outvars['Foul Ball'].vals)[0]

    # sim.outvars['Landing Dist [m]'].addVarStat(stat='gaussianP',
    #                                            statkwargs={'p': 0.90, 'c': 0.50})
    # sim.outvars['Landing Dist [m]'].addVarStat(stat='gaussianP',
    #                                            statkwargs={'p': 0.10, 'c': 0.50})
    # print(sim.outvars['Landing Dist [m]'].stats())
    # mc.plot(sim.outvars['Time [s]'], sim.outvars['Distance [m]'], highlight_cases=homerun_indices)
    # mc.plot(sim.outvars['Time [s]'], sim.outvars['Speed [m/s]'],
    #         highlight_cases=homerun_indices)
    fig, ax = mc.plot(sim.outvars['X [m]'],
                      sim.outvars['Y [m]'],
                      sim.outvars['Z [m]'],
                      title='Baseball Trajectory',
                      highlight_cases=homerun_indices,
                      plotkwargs={'zorder': 10})
    plot_baseball_field(ax)
    ax.scatter(sim.outvars['Landing X [m]'].nums,
               sim.outvars['Landing Y [m]'].nums,
               0,
               s=2,
               c='k',
               alpha=0.9,
               marker='o')
    # fig.set_size_inches(7.0, 7.0)
    # plt.savefig('baseball_trajectory.png', dpi=100)

    sim.plot(highlight_cases=homerun_indices)

    fig, axs = mc.multi_plot(
        [sim.invars['Launch Angle [deg]'], sim.outvars['Landing Dist [m]']],
        title='Launch Angle vs Landing Distance',
        cov_plot=False,
        highlight_cases=homerun_indices)
    # fig.set_size_inches(8.8, 6.6)
    # plt.savefig('launch_angle_vs_landing.png', dpi=100)
    plt.show(block=False)

    ## Calculate and plot sensitivity indices
    sim.calcSensitivities('Home Run')
    fig, ax = sim.outvars['Home Run'].plotSensitivities()
    # fig.set_size_inches(10, 4)
    # plt.savefig('landing_dist_sensitivities.png', dpi=100)
    plt.show()

    return sim
def retirement_example_monte_carlo_sim():

    sim = mc.Sim(name='retirement',
                 ndraws=ndraws,
                 fcns=fcns,
                 firstcaseismedian=True,
                 samplemethod='sobol_random',
                 seed=seed,
                 singlethreaded=False,
                 savecasedata=False,
                 verbose=True,
                 debug=True)

    sp500_mean = 0.114
    sp500_stdev = 0.197
    inflation = 0.02
    nyears = 30

    for i in range(nyears):
        sim.addInVar(name=f'Year {i} Returns',
                     dist=norm,
                     distkwargs={
                         'loc': (sp500_mean - inflation),
                         'scale': sp500_stdev
                     })

    sim.addInVar(name='Beginning Balance',
                 dist=uniform,
                 distkwargs={
                     'loc': 1000000,
                     'scale': 100000
                 })
    sim.addConstVal(name='nyears', val=nyears)

    sim.runSim()

    wentbrokecases = [
        i for i, e in enumerate(sim.outvars['Broke'].vals) if e == 'Yes'
    ]

    mc.plot(sim.invars['Year 0 Returns'],
            sim.outvars['Final Balance'],
            highlight_cases=0,
            cov_plot=False)
    mc.plot(sim.outvars['Broke'])
    mc.plot(sim.invars['Beginning Balance'], highlight_cases=0)
    fig, ax = mc.plot(sim.outvars['Date'],
                      sim.outvars['Ending Balance'],
                      highlight_cases=wentbrokecases,
                      title='Yearly Balances')
    ax.set_yscale('symlog')
    ax.set_ylim(bottom=1e4)
    fig.set_size_inches(7.6, 5.4)
    plt.savefig('yearly_balances.png', dpi=100)

    sim.genCovarianceMatrix()
    fig = plt.figure()
    yearly_return_broke_corr = []
    for i in range(nyears):
        corr = sim.covs[sim.covvarlist.index('Broke')][sim.covvarlist.index(
            f'Year {i} Returns')]
        yearly_return_broke_corr.append(corr)
    plt.plot(range(nyears), yearly_return_broke_corr, 'k')
    plt.plot(range(nyears), np.zeros(nyears), 'k--')
    plt.title('Correlation Between Yearly Return and Going Broke')
    plt.ylabel('Correlation Coeff')
    plt.xlabel('Year')
    fig.set_size_inches(7.6, 5.4)
    plt.savefig('return_broke_corr.png', dpi=100)

    plt.show()

    return sim