…in which I post yet again on a topic about which I know relatively little… which arguably is not a recipe for a long and happy professional life
It seems like every self-respecting simulation package has at least a modicum of animation capability – and many are, in fact, designed around pretty impressive animators. I figured I would have to supply at least bare-bones 2-D animation sooner or later… but I hoped it would be later. While I felt like I had a pretty good handle on what a core simulation engine looks like, I didn’t really have a clue when it came to animation. Animation struck me as a large, amorphous black box that would suck up copious amounts of my time while still resulting in an amateurish solution. I just didn’t want to deal with it.
So I built the rudiments of a simulation engine, created some models using that engine, and started running them. And, of course, I almost immediately ran into the problem of verifying those models, even at the most basic level. How am I supposed to make sure these models are behaving as I intend? Sure, I can model an M/M/1 queue and see if queue size and time conform to the standard analytically-derived results. But if they don’t, how do I figure out what’s going wrong? What about other models, with no analytic solutions?
Yes, I could manually trace the simulation, event-by-event, but I quickly tired of that approach. Like (probably) most software developers, I’m easily bored by repetition, and inherently lazy – isn’t that why we like to automate stuff? Spending hours tracing and debugging the simplest of models was just not going to cut it.
Animation seemed to be the most straightforward solution. In theory, at least, animation should quickly make the most obvious bugs, well, obvious. I really did not want to go there yet, but if the only alternative was carefully pouring through reams of trace output, then perhaps it was, in fact, time to go there. So I waded my way into the Alice-in-Wonderland world of animation technology, and dove down the first rabbit hole that presented itself.
The idea of writing about random number generation (I mean, pseudo-random number generation, but that term involves way too much typing) makes me extremely nervous. When it comes to that topic, I think of two groups of people:
The High Priesthood. The individuals (one or two dozen, in my imagination) who develop, test and understand these generators
The thousands who make fools of themselves writing about random numbers on the Internet.
I am definitely not in the first category; I’ll keep my fingers crossed that this post doesn’t put me solidly into the second.
Back in the day, when dinosaurs roamed the earth and computers were Big Machines in Large Rooms with Raised Floors, there was a popular expression in the industry – No one ever got fired for buying IBM. The Mersenne Twister is the IBM of pseudo-random number generators. It’s not the fastest or most efficient generator. It may or may not deliver the “best” results (a debate I’ll leave to the aforementioned priesthood). But it is fast enough, good enough and best-known of the modern vintage of random number generators – so it has become a de facto standard. If you were to recommend a different generator that I haven’t heard of, I’d probably ask how it compares to the Mersenne Twister. Python’s random module uses MT19937, the most commonly used (and heavily tested) version of Mersenne Twister. The standard library designers definitely could have chosen worse. But is it good enough for our discrete event simulator?
A couple of previous posts (here and here) presented three Python-based alternatives for expressing process or agent-based behavior that takes place over (or blocks for) simulated time: generators, greenlets and tasklets.
So which approach is best? There are (at least!) three factors to consider:
Ease of use – ease-of-coding, expressiveness, maintainability.
Eco-system factors – compatibility with the rest of my chosen Python tool chain, now and in the future.
Performance.
Let’s have a look, starting with ease-of-use. Read more »
My last two posts (here and here) introduced three Python-based alternatives for expressing simulation process or agent-based behavior that takes place over (or blocks for) simulated time:
Generators, a core feature of the Python language
Greenlets, provided by the third-party greenlet Python extension package
Tasklets, provided by two standalone Python distributions, Stackless Python and PyPy
While those posts included a few brief code snippets, perhaps now is a good time to add meat to the bones and present the full code for one (albeit simple) simulation model. We’ll model the classic M/M/1 queue, a system with a single queue and a single server. Both interarrival and service times are exponentially distributed. There is no upper bound on the queue length. We’ll implement a process-oriented simulation in two ways; one using generators, the other, greenlets. (With small modifications, we could convert the greenlet-based code to tasklets.)
In my last post, I discussed Python’s built-in support for coroutines via generators. While we can use generators to implement simulation process code, the essentially stackless nature of generator functions limit their expressiveness and power.
Once we venture beyond Python’s standard library, there are a couple of other options that facilitate completely stackful coroutines: greenlets and tasklets.
As I mentioned here, coroutines provide a means to express processes occurring over simulated time in a pretty natural way. Python has one built-in mechanism, the generator, which enables coroutine-like functionality. Two other flavors of coroutine, greenlets and tasklets, are implemented by third-party packages; these will be discussed in a later post.
There are simulation tools that require you to define your model entirely in the form of a program, or source code – whether via an existing general purpose programming language or a special purpose simulation language. Other tools require you to define models totally through data: graphical, tabular, or some combination of the two. This is usually a selling point – “no programming required!!!” Finally, there are packages that combine both approaches.
Is “No programming required!” a bug or a feature? That’s a religious question that I’d rather avoid, at least for now. Let it suffice to say that I believe that program code has its place – but then again, I develop software for a living, so perhaps I’m just a bit biased. In any event, I fall into that third camp – both data and code. For now, the question I’d like to explore is not whether modelers should write code, but how and what kind.
I started my career in simulation building process-based models. That is, of course, a classic approach to simulation modeling, and it generally worked pretty well for the manufacturing applications that I was involved with. Fabrication and assembly work flows to often map very nicely to processes in a simulation model.
As I mentioned in my introductory post, I started down this road as a software engineer turned simulation practitioner, who thought he might be able to build a better – or at least different – mousetrap. Which naturally leads to the question: what am I trying to do differently? You might be tempted to translate that into “What are your requirements?”, but at this stage, I prefer to think of them more fuzzily as goals. I started off with five:
Up until now, I have studiously avoided having an online presence, which is at least supposed to be unusual for a “technology professional” such as myself. I ignored Facebook until my eldest daughter signed up, at which point both my wife and I opened accounts in order to “monitor” her. (And that so-called monitoring lasted about a week or two, at which point we decided to make the lazy decision to trust her. I haven’t logged in in… I probably shouldn’t say. Our daughter has somehow survived largely unscathed despite our lack of oversight.) I accepted a LinkedIn invitation not long after it appeared, but then proceeded to largely ignore that as well for months on end.
Why? I’d like to think it’s because I had more important things to do, but truthfully, I can and do waste time as well as the next guy. Am I a bit of a Luddite? Yeah, perhaps. Is it because I have nothing useful or interesting to say? Well, I suppose we’re about to find out 🙂
I’m certainly not afraid of speaking in public, and, in fact, I’ve done a fair amount of that (albeit not in a professional capacity). I am, however, perhaps a bit afraid of writing in public. I am acutely aware that the written word, which may be read, re-read and otherwise steamed over, is a completely different beast than the ephemeral spoken word. Once it’s on paper – or even worse, the Internet – plausible deniability goes out the window. As the well-known Mark Twain quote goes, “It is better to keep your mouth closed and let people think you are a fool than to open it and remove all doubt.”