(I think your stepwise problem is better to be solved without agents, see
below.)

I realized that the *rng* actually is conflated, it keeps both the state
for the random number generator AND the algorithm used for the random
number generation. This is usually not a problem, since the state-size and
usage is dependent on the particular random number generator, but it
becomes a problem when we need to separate and multithread things.

One solution would be to either re-implement the algorithm (by Knuth) used
in the original Sun Java random implementation, or use the experimental
library Four [1] by Gary Fredericks that does exactly this.

What you would like to do is to be able to feed the rng-algorithm with the
state (it is just a 64 bit long), and simply take the random-result
generated from it, and store the state in the agent together with the rest
of the simulation state.

Dubious Speculations:
This makes it necessary to know that the agents are called in the same
order (if the influence on each other). Given the non-guarantee of ordering
in the nature of Java Threads and how agents rely on them I don't think you
can expect your result to be reproducible. Here I assume that the incoming
calls to agents aren't guaranteed to strictly ordered among different
agents, even though the agents reside in one of two thread-pools (the send-
vs. send-off pools). If two agents sent messages that arrived a third agent
in different order, the rng-state would differ between the runs). Please
correct me if I'm wrong on this one. A possible clever way around this
could be to send the rng state together with the message arriving at the
agent, to make the agent at least react to the state in a similar way. If
you have some kind of continous magnitudes in the simulation - like
pheromones - the simulation would maybe converge to similar results since
the interaction effects would be reproducible but this is indeed a very
far-fetched hypothesis.

So only if your Person transform functions are commutative (ie gives the
same result whichever order they was called in every timestep) the
simulation could be reproducible by storing the local random generator seed
in each Person.

If it's just speed you are after, do use either the java 1.7
ThreadLocalRandom (at least try out if this really gives any performance
boost).

A naive ThreadLocalImplementation implementation of clojure.core/rand would
be:

(defn rand
  "Returns a random floating point number between 0 (inclusive) and
  n (default 1) (exclusive)."
  {:added "1.0"
   :static true}
*  ([] (.nextDouble (java.util.concurrent.ThreadLocalRandom/current)))*
  ([n] (* n (rand))))

but as you can see in the source code, random integers are generated using
a call to (rand), multiplied with the integer and floored (when converting
to int), so there are ways to get an limited range int more efficiently
(check the source code for java.util.Random, which makes various tricks for
getting just enough random bits out.

As always, measure performance (Hugo Duncans Criterium,
criterium.core/bench is a really good start). Numerical double operations
are cheap, memory accesses - in this case to resulting data structures or
other agents and likely context switches - could as well be the more
expensive part.

BTW: It looks like the problem you want to solve would benefit much from
being formulated as a two-step problem, one where you applied all the
incoming calls to each Person, and another where you sorted the messages to
each Person in some reproducible order, like

* = has an incoming message

initial state: Person A will hit Person B, just for the lulz.

apply "map": A* B C
resulting actions sorted by Receiver: [A hits B]
apply these: A B* C
[B gets mad and throw raspberry pies at both A and C]
A* B C*
[A yells at B, C yells at B] <- mind the ordering! Always apply A's action
before Cs (or let B's random seed shuffle a sorted ordering of the same to
avoid ordering biases and make it reproducible)
A B* C
[B sends a stern look to A and C]
<no further actions>

If you makes the message passing explicit instead of
Java-thread-call-uncertain-implicit (which IS possible and parallelizeable
in a stepwise simulation!) you can still parallelize it in many ways (for
example with reducers) and at the same time make simulations reproducible,
and you'll avoid a lot (N²) of potentially expensive context switching.

/Linus - take everything I say with a sand-pile avalanche of salt-grains.

[1] https://github.com/fredericksgary/four


2014-06-06 18:37 GMT+02:00 Mars0i <marsh...@logical.net>:

> One more point:
>
> I would save the system-time-determined seed of the initial RNG to a file
> (i.e. the RNG used to generate seeds for each Person's RNG).  I believe
> this will allow me to re-run a simulation with identical results, by
> seeding the initial RNG with the seed saved from the previous simulation
> run.  Let me know if this doesn't make sense.  Thanks.
>
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clojure@googlegroups.com
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> clojure+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to clojure+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to clojure+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to