In this guide we’ll try to explain what GarlicSim is all about. You know that GarlicSim is a Pythonic framework for simulations, but what does that mean?
Before trying to define what “simulation” means, let’s try to think of a few examples of simulations:
With the above examples in mind, here is an attempt to define “simulation”:
Simulation is the act of mimicking a real-world phenomenon symbolically in a computer, without the phenomenon actually happening in reality.
This definition is almost good enough. It ignores the fact that some simulations are just abstract, like cellular automata. GarlicSim is designed to handle all of the simulations listed here, including the abstract ones.
People often ask, if GarlicSim is so general that it applies to all simulations, how useful can it be? To answer that we need to look at what all the simulations we mentioned above have in common, and define that as the basic characteristic of a “simulation”.
The answer is:
A simulation is something that:
- Defines the concept of a world state, and
- Defines a step function, which is a function that given a world state, outputs the next world state.
It can be thought of as a frozen moment in time in the world of the simulation. A world state contains all the information there is about that moment in time in the simulation.
In the terminology of GarlicSim, we shorten the term “world state” into simply state. A state is actually a class, defined as garlicsim.data_structures.State. The class itself doesn’t define much; every simulation will make its own State subclass and store data in its state instances as data attributes. For example, the basketball simulation might store a floating-point number in state.height.
It’s a function that given the world state in a certain point of time, calculates the world state of the next moment in time.
A little digression: As we all know, in our physical reality there is no such thing as “the next moment in time”, since time is continuous and between every two moments in time there is another moment. However, when doing computer simulations we assume that time is discrete, not continuous, because it makes it much easier for us to work with. We basically assume that time is not a continuous line, but a line made of points; if we take two adjacent points, there is a finite time interval between them, which might be a second or a minute or a year, depending on the context, and there are no other moments in that interval between them. This decision is of course a compromise, and it introduces inaccuracy into our simulations; however, that accuracy can be made as small as desired by increasing the resolution of points in the timeline.
Back to the step function. As we said, the step function takes the state in a certain point in time and calculates the state in the next point of time.
When you think of it, the step function is actually the very heart of the simulation. There are other parts that a simulation must define, such as how to display a state on the screen, or how to create the initial state. But the most important thing in a simulation is its step function. The step function is the one responsible for doing the actual work of simulating, and thus it defines the “world rules” of a simulation. For example, by changing the step function of a simulation of Newtonian physics, one can transform it into a simulation of Special Relativity. Thus it can be said that the step function is the simulation.
Up to now we’ve been using the word “simulation” for two different meanings. Therefore I would now like to “split” it into two terms, so our terminology will be more precise. Besides the term “simulation”, I would like to introduce the term simulation package, or as we will frequently abbreviate it, simpack.
Every simulation has a simpack. But one simpack may be used in many simulations. If a simpack can be said to describe the laws of a certain world, then a simulation is a story within that world. For example, we may have a simpack for simulating bouncing basketballs, which will describe exactly how basketballs move and bounce; but if we will want to actually simulate a basketball, we will have to create a simulation associated with that simpack. The story of our specific basketball will be contained in the simulation, not in the simpack.
Therefore, a simpack can be thought of as a “simulation type.” We talked before about how important the step function is; the step function is defined within the simpack.
What we called “simulation” so far we’ll also refer to as a project. This is because it’s the name of the class corresponding to it: garlicsim.Project.
“Simpack”, however, does not correspond to any class in GarlicSim; it is just a special kind of Python package [1] that defines a few key functions, among them the step function.
The core of GarlicSim itself does not contain any simpacks. Simpacks can be thought of as third-party add-ons to GarlicSim. GarlicSim will eventually be shipped with a standard library of simpacks, covering as many simulation domains as possible.
One can say that there are two “levels” to GarlicSim development:
People who develop simpacks need not understand the inner workings of GarlicSim: All they need to know is the API between GarlicSim and the simpack that they intend to write. It can be said that from the point of view a GarlicSim developer, simpack developers are “users”, while from the point of view of a simpack developer, “users” are people who just use the simpack and may not know how it works or how GarlicSim works, (and may as well be using GarlicSim entirely from a GUI without even knowing Python.)
Footnotes
| [1] | For the benefit of the reader who does not know what a Python package is: It is similar to a Python module, except that it is a directory which has modules in it. The directory must have a __init__.py, even an empty one, to be considered a Python package. |