(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.