Java Reference
In-Depth Information
Another way of working it out is to simulate rolling two dice using random numbers between
1 and 6, adding up the number of times that each result was picked, and dividing by the num-
ber of rolls. This is actually a really simple Monte Carlo simulation. The more times we sim-
ulate rolling the dice, the more closely we approximate the actual result—so we really want
to do it a lot.
Example 6-3
shows how we can implement the Monte Carlo approach using the streams lib-
rary.
N
represents the number of simulations we'll be running, and at we use the
IntStream
range function to create a stream of size
N
. At we call the
parallel
method in
order to use the parallel version of the streams framework. The
twoDiceThrows
function
simulates throwing two dice and returns the sum of their results. We use the
mapToObj
meth-
od in in order to use this function on our data stream.
Example 6-3. Parallel Monte Carlo simulation of dice rolling
public
public
Map
<
Integer
,
Double
>
parallelDiceRolls
() {
double
double
fraction
=
1.0
/
N
;
return
return
IntStream
.
range
(
0
,
N
)
.
parallel
()
.
mapToObj
(
twoDiceThrows
())
.
collect
(
groupingBy
(
side
->
side
,
summingDouble
(
n
->
fraction
)));
}
At we have a
Stream
of all the simulation results we need to combine. We use the
group-
ingBy
collector, introduced in the previous chapter, in order to aggregate all results that are
equal. I said we were going to count the number of times each number occured and divide by
N
. In the streams framework, it's actually easier to map numbers to
1/N
and add them, which
is exactly the same. This is accomplished in through the
summingDouble
function. The
Map<Integer, Double>
that gets returned at the end maps each sum of sides thrown to its
probability.
I'll admit it's not totally trivial code, but implementing a parallel Monte Carlo simulation in
five lines of code is pretty neat. Importantly, because the more simulations we run, the more
closey we approximate the real answer, we've got a real incentive to run a lot of simulations.
This is also a good use for parallelism as it's an implementation that gets good parallel spee-
dup.
I won't go through the implementation details, but for comparison
Example 6-4
lists the
same parallel Monte Carlo simulation implemented by hand. The majority of the code imple-
mentation deals with spawning, scheduling, and awaiting the completion of jobs within a