<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>code-spot</title>
	
	<link>http://code-spot.co.za</link>
	<description>a programming blog</description>
	<lastBuildDate>Mon, 30 Nov 2009 11:19:34 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/code-spot" /><feedburner:info uri="code-spot" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Tips for Designing and Implementing a Stimulus Response Agent</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/G9oUzj2Wfi0/</link>
		<comments>http://code-spot.co.za/2009/10/25/tips-for-designing-and-implementing-a-stimulus-response-agent/#comments</comments>
		<pubDate>Sun, 25 Oct 2009 20:35:41 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Game Development]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[artificial intelligence]]></category>
		<category><![CDATA[convolution]]></category>
		<category><![CDATA[filtering]]></category>
		<category><![CDATA[Kalman filter]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[PID controller]]></category>
		<category><![CDATA[racing game ai]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[random steering]]></category>
		<category><![CDATA[response curve]]></category>
		<category><![CDATA[Special Numbers Library]]></category>
		<category><![CDATA[stimilus response agent]]></category>
		<category><![CDATA[system design]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=776</guid>
		<description><![CDATA[
(Original Image by everyone’s idle.)
This post was a originally published on Luma Labs, now dead.
As old as stimulus-response techniques are, they still form an important part of many AI systems, even if it is a thin layer underneath a sophisticated decision, planning, or learning system. In this tutorial I give some advice to their design [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="brain" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/brain.png" border="0" alt="brain" width="500" height="366" /><br />
(<a href="http://www.flickr.com/photos/mgdtgd/3507973704/">Original Image</a> by <a href="http://www.flickr.com/photos/mgdtgd/">everyone’s idle</a>.)</p>
<p><em>This post was a originally published on Luma Labs, now dead.</em></p>
<p>As old as stimulus-response techniques are, they still form an important part of many AI systems, even if it is a thin layer underneath a sophisticated decision, planning, or learning system. In this tutorial I give some advice to their design and implementation, mostly out of experience gained from implementing the AI for some racing games.</p>
<p>A <em>stimulus response agent</em> (or a <em>reactive agent</em>) is an agent that takes inputs from its world through sensors, and then takes action based on those inputs through actuators. Between the stimulus and response, there is a processing unit that can be arbitrarily complex. An example of such an agent is one that controls a vehicle in a racing game: the agent “looks” at the road and nearby vehicles, and then decides how much to turn and break.</p>
<p><span id="more-776"></span></p>
<p>This definition is so broad that it is hard to think of agents that are <em>not</em> stimulus response agents. Some agents base their actions not on inputs, but on their internal state alone. See for example how <a href="http://code-spot.co.za/2008/12/07/random-steering-7-components-for-a-toolkit/">random steering algorithms</a> can lead to interesting behaviour.</p>
<p>Some agents don&#8217;t act. They just digest. The only way they can be useful if we look at what they are “thinking”. In fact, they are often designed with the sole purpose of “telling” us what they think, and they are not usually called <em>agents</em>, but rather decision systems. A face recognition system is an example of this. Of course, if we consider “telling” or “deciding” an action, these decision system become stimulus response agents too – but since we do not think of them as agents, the distinction is useful.</p>
<h2>Design</h2>
<h3>1. Do not design your system around an overly simplistic view</h3>
<p>The typical presentation of a stimulus response agent looks like this:</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="SRA_simple" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/SRA_simple.png" border="0" alt="SRA_simple" width="303" height="52" /></p>
<p>This presentation, while technically correct, is suitable only for flowers blowing in the wind. A real-world stimulus-response agent might look more like this:</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="sra_complex" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/sra_complex.png" border="0" alt="sra_complex" width="436" height="332" /></p>
<p>Note that there are five factors that influence decisions:</p>
<ul>
<li><strong>Game state</strong> is the mode of the game. For example, when an agent can be in a PLAY state (actively competing against the player) or a CHILL state (after taking over from the player at the end of the game.</li>
<li><strong>Global world state </strong>is the current conditions of the world, such as the weather or time of day.</li>
<li><strong>Local world</strong> <strong>state</strong> is what is normally thought of as the “stimulus”. It is the properties of the world around the agent that changes as the agents moves or otherwise acts in the world. For example, the shape of the path near a path following agent is part of the local world state.</li>
<li><strong>Agent parameters</strong> constitute the fixed limits of the agent&#8217;s sensory processing, and reactionary systems. For example, how far can the AI see, how quickly will it react, and how high can it jump. These parameters often describe the bounds for a state variable.</li>
<li><strong>Agent state</strong> is the changing parameters of the agent&#8217;s behaviour.</li>
</ul>
<p>Note that all these can be mapped to the simplistic view of our agent. However, it is important to recognise the differences in these groups of variables, because the agent is made aware of them (connected to them) in different ways.</p>
<p>The world state is not sensed, but communicated through passed parameters, or a query to the world state object.</p>
<p>The game state is enforced by the game system, and typically the agent does not query or sense the game state – it is communicated from the outside.</p>
<p>The local world state is sensed by the agent through its sensors. Typically this means the agent must have hooks into the world. This data can be noisy or incomplete, so the agent might use filtering, and hence will store its own processed copy of the data.</p>
<p>The agent parameters of are partially hard-coded, and partially generated on construction, or read from a file. These do not change over the agent&#8217;s life time.</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="agent_state" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/agent_state.png" border="0" alt="agent_state" width="171" height="105" /></p>
<p>The agent state is calculated on updates. It has two parts:</p>
<ul>
<li>The <strong>discrete state</strong> is usually implemented as a state machine. In a vehicle driving agent, the discrete states can be PULL_AWAY, NORMAL, WRONG_WAY, and so on.</li>
<li>The <strong>continuous state</strong> of an agent is the state determined by a set of parameters. For a vehicle driving agent, these can include “deviation_from_path”, “distance_from_closest_player”, “aggressiveness” and so on. Note that the continuous state for every discrete state can be described by a different set of parameters, possibly overlapping.In general, a different set of response equations will be used for every discrete state. In fact, the sole purpose of the state machine is to select the correct set of response equations for every situation.</li>
</ul>
<p>The table below summarises the factors that influence a stimulus response agent&#8217;s decisions.</p>
<table border="0" cellspacing="0" cellpadding="2" width="492">
<tbody>
<tr>
<td width="145" valign="top"><strong>Factor</strong></td>
<td width="345" valign="top"><strong>Source</strong></td>
</tr>
<tr>
<td width="145" valign="top">Game state</td>
<td width="345" valign="top">Game system</td>
</tr>
<tr>
<td width="145" valign="top">Global world state</td>
<td width="345" valign="top">World</td>
</tr>
<tr>
<td width="145" valign="top">Local world state</td>
<td width="345" valign="top">Sensors</td>
</tr>
<tr>
<td width="145" valign="top">Physical parameters</td>
<td width="345" valign="top">Hard-coded / File / Generated</td>
</tr>
<tr>
<td width="145" valign="top">Agent state</td>
<td width="345" valign="top">Calculated</td>
</tr>
<tr>
<td width="145" valign="top">
<ul>
<li>Discrete State</li>
</ul>
</td>
<td width="345" valign="top">State machine transitions</td>
</tr>
<tr>
<td width="145" valign="top">
<ul>
<li>Continuous State</li>
</ul>
</td>
<td width="345" valign="top">Equations</td>
</tr>
</tbody>
</table>
<h3>2. Clearly distinguish between objects that have state, and those that do not (or should not)</h3>
<p>It is easy to build objects that have states when they should not. It is, for example, reasonable to design a path-following object so that it keeps track of an agent&#8217;s progress along the path (such as the last node reached), to simplify communication between the agent and the path. In this scenario, the communication looks like this:</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="state_wrong1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/state_wrong1.png" border="0" alt="state_wrong1" width="285" height="114" /></p>
<p>There are at least two problems with this set-up:</p>
<ul>
<li>every agent must have its own copy of the path; and</li>
<li>the agent can&#8217;t ask any path information that violates the path object&#8217;s assumption about where the agent is.</li>
</ul>
<p>To illustrate the last point, consider the situation where the path keeps track of the last node reached by the agent, and updates that node as the agent reports its position to the path object. It uses this node and the next node to interpolate a suitable position for the agent to move to. All is fine, until the agent needs information about the future, for example, it&#8217;s projection one second from now on the path. One second from now, the agent may have reached another node, something this simple system cannot handle properly.</p>
<p>Another way to do this, is for the agent to store the last node reached and pass it along its position in queries:</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="state_wrong2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/state_wrong2.png" border="0" alt="state_wrong2" width="288" height="150" /></p>
<p>This does not solve the problem really – must the agent now store a separate node for queries into the future?</p>
<p>The best solution is to have a path manager. It has two responsibilities:</p>
<ul>
<li>to store any agent state information relating to the path – the last node reached, in our example; and</li>
<li>to handle calculations for queries (based only on data from the path).</li>
</ul>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="states_correct" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/states_correct.png" border="0" alt="states_correct" width="511" height="131" /></p>
<p>Now, when the agent asks the path manager about its projection 1 second from now, the path manager can check against the path whether a node will be reached, and perform the correct calculation. [In practise, the agent will transform time into distance travelled in time at its current velocity, so that the path manager only needs to know about distance, not time].</p>
<p>Every agent must have its own path manager, but the path managers can share the same path.</p>
<p>Consider another, slightly different, example. A certain agent has a “angriness” factor, which is randomised every 10 updates between two fixed extremes. Every type of agent has a different set of extremes (a monster will have higher extremes than a cow, for example), which helps determine the agent&#8217;s “personality”. It is easy to dump the extremes and the current value in one object (typically, the agent object). This is a poor design for two reasons:</p>
<ul>
<li>There is unnecessary duplicated data, with the associated disadvantages (such as making network packets bulkier, making save files of the game state bigger, and so on).</li>
<li>The distinction between of agent state and agent parameters gets muddy. This makes it easier to make mistakes, overcomplicate the design, and introduce unnecessary inefficiencies.</li>
</ul>
<p>A better design is to put the extremes into an “angriness profile” object, which can be shared by agents of the same type; in the example there will be two instances, one for cows and one for monsters.</p>
<p>Note that this issue goes hand-in-hand with preferring composition over inheritance hierarchies.</p>
<h3>3. Draw pictures to show the ideal response to a given stimulus situation</h3>
<p>It is very important to define clearly what you want the agent to do given some stimulus. The following graphs shows a few examples for a vehicle steering agent.</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="166" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="steering_graph" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/steering_graph.png" border="0" alt="steering_graph" width="160" height="159" /></td>
<td width="166" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="nitro_graph" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/nitro_graph.png" border="0" alt="nitro_graph" width="160" height="159" /></td>
<td width="166" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="nitro_graph2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/nitro_graph2.png" border="0" alt="nitro_graph2" width="160" height="159" /></td>
</tr>
<tr>
<td width="166" valign="top"><span style="color: #408080;">Steering as a function of angular deviation from path.</span></td>
<td width="166" valign="top"><span style="color: #408080;">Nitrous usage as a function of angular deviation from path (reckless driver).</span></td>
<td width="166" valign="top"><span style="color: #408080;">Nitrous usage as a function of angular deviation from path (conservative driver).</span></td>
</tr>
</tbody>
</table>
<p>Most variables will depend on more than one other variable. Do not worry too much about that when drawing these diagrams. Focus on typical cases, and jot down any requirements or assumptions.</p>
<p>Also, do not try to write down any equations for your graphs. Any relationship can always be represented by a <em>response curve</em>, something that is much quicker to set up and easy to implement. A response curve is essentially a look-up table with linear interpolation. It can be used to approximate arbitrary functions by specifying the input range, and a number of output samples. The idea is discussed more thoroughly in AI Programming Wisdom 1 (<em>The beauty of Response Curves </em>by Bob Alexander).</p>
<h3>4. Draw System Diagrams to show how variables relate</h3>
<p>In a complicated system, it is easy to lose track of how variables relate. A forgotten relationship can often lead to behaviour that is hard to understand. Having an easy-to-reference diagram will be a great help in debugging faulty behaviour.</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="flow_diagram" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/flow_diagram.png" border="0" alt="flow_diagram" width="537" height="486" /></p>
<p>The diagram above distinguishes between relationships under AI control, and relationships that are under physics control – i.e. Relationships that cannot be changed by the agent. The diagram also indicates whether a relationship is positive (i.e. more of the one will result in more of the other), or negative (i.e. more of one will result in less of the other).</p>
<h3>5. Use a spreadsheet to graph response curves to typical situations</h3>
<p>Once you have your equations, you have to make sure that they actually describe the curves you intend. Also, in complicated formulas, it is important to check how these curves behave on typical data sets – <em>especially if you employ filtering </em>(see below).</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="spread_sheet_graph" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/spread_sheet_graph.png" border="0" alt="spread_sheet_graph" width="479" height="358" /></p>
<h3>6. Eliminate unimportant feedback loops.</h3>
<p>Feedback is important for proper control in most systems. However, every loop makes it more difficult to analyse and understand the system – something that becomes apparent when things go wrong. If your system is complex, try to remove some of the loops (by removing some of the dependencies). You can always complicate your system <em>once you have it working</em>.</p>
<h3>7. Prototype your agent on a computer algebra system</h3>
<p>A computer algebra system (CAS) is the perfect environment to prototype a stimulus response agent:</p>
<ul>
<li>The high-level syntax, dynamic variables, and fat libraries allows you develop designs quickly, so that you can try out more designs.</li>
<li>The built-in graph plotting capabilities are useful for debugging (see below) and understanding complex designs.</li>
<li>You can simulate scenarios that are hard to obtain in the actual game, leading to a design that is much more robust.</li>
</ul>
<h2>Filtering</h2>
<h3>8. Filtering input, output, and intermediate values can drastically improve behaviour</h3>
<p>There are several reasons to use filtering in your agent:</p>
<ul>
<li>To reduce noise that might confuse your agent about the state the world (or it) is in.</li>
<li>To smooth out (and hence fill in) incomplete data. For example, a path made of line segments can be “filtered” so that it appears smooth to the agent.</li>
<li>To make the actions of the agent seem more determined. An agent that changes it&#8217;s mind 10 times a second is not very believable.</li>
<li>To prevent abrupt reactions to changes in the world that will make the agent less believable.</li>
</ul>
<p>There are several approaches to filtering. One approach that works well in many cases is to change a variable only by some maximum amount, like this:</p>
<pre>updateFilteredX(x)
{
   filteredX += clamp(x – filteredX, -maxIncX, maxIncX);
}</pre>
<p>Here maxIncX is much smaller than typical values of x (using a tenth is a good starting point).</p>
<p>When you have many filtered variables, it becomes unmanageable to filter them all in this way – for every variable you want to filter, you need three extra variables, and you need to remember to use the right updating technique whenever the variable changes. It is better to encapsulate the filtering in a special class (as has been done in the <em>Special Numbers Library </em>– see <a href="http://specialnumbers.google.com/">http://specialnumbers.google.com</a>).</p>
<p>Other approaches to filtering include:</p>
<ul>
<li>statistical filtering techniques, such as <a href="http://en.wikipedia.org/wiki/Recursive_least_squares_filter">least squares</a> and <a href="http://en.wikipedia.org/wiki/Kalman_filter">Kalman</a> filtering;</li>
<li><a href="http://en.wikipedia.org/wiki/Digital_filter">convolutional filters</a>; and</li>
<li><a href="http://en.wikipedia.org/wiki/PID_controller">PID controllers</a>.</li>
</ul>
<h3>9. Make your filtering technique frame-rate independent, and do it from the start</h3>
<p>The rate of updates of filters can have a dramatic effect on resulting behaviour. This rate can either fluctuate naturally (as it goes with frame rate), or be the difference between a Debug and Release versions of your application.</p>
<p>The resulting changes in behaviour makes it hard to:</p>
<ul>
<li>debug faulty behaviour; and</li>
<li>spot problems to begin with (because it always works fine on <em>your</em> machine!).</li>
</ul>
<p>How you make your filtering frame-rate independent depends on the method of filtering used. For the system explained above, it merely means updating with an amount proportional to the elapsed time (between updates).</p>
<pre>updateFilteredX(x, elapsedTime)
{
   filteredX += clamp(x – filteredX,
                -maxIncX*elapsedTime, maxIncX*elapsedTime);
}</pre>
<p>The updateFilteredX function above will use a smaller value for maxIncX than the one that does not compensate for time. It is for this reason that you should implement frame-rate independence <em>from the start</em>. Otherwise you will need to re-tweak all your values increment values <em>again</em>.</p>
<h3>10. Do not filter the channels of n-dimensional data separately</h3>
<p>If you filter a position, for example, by the method described above, you might be tempted to do something like the following:</p>
<pre>updateFilteredXYZ(point)
{
   filteredPoint.x += clamp(point.x – filteredPoint.x,
                               -maxInc, maxInc);
   filteredPoint.y += clamp(point.y – filteredPoint.y,
                               -maxInc, maxInc);
   filteredPoint.z += clamp(point.z – filteredPoint.z,
                               -maxInc, maxInc);
}</pre>
<p>The above code will lead to strange behaviour. Consider for example,</p>
<ul>
<li>filteredPoint = (0, 0, 0),</li>
<li>point = (2, 1, 0) (for the next 4 updates)</li>
<li>maxInc = 0.5</li>
</ul>
<p>The variable filteredPoint will now go through these values on the next four updates:</p>
<p>(0.5, 0.5, 0)</p>
<p>(1.0, 1.0, 0)</p>
<p>(1.5, 1.0, 0)</p>
<p>(2.0, 1.0, 0)</p>
<p>If this filteredPoint represents an agent trying to reach (2, 1, 0)&#8217;s heading, the agent will first move to point (1, 1, 0), and then turn towards (2, 1, 0), and move to it.</p>
<p>The correct way to implement filtering for multi-dimensional data is to add a clamped amount of difference between the value and the filteredValue to the filtered value.</p>
<pre>updateFilteredXYZ(point)
{
   updateAmount = clamp((filteredPoint – point).len(),
                        0, maxInc)
   filteredPoint += (point – filteredPoint) * updateAmount;
}</pre>
<p>Now the next four values of filteredPoint lie in a straight line:</p>
<p>(0.316, 0.632, 0)</p>
<p>(0.632, 1.265, 0)</p>
<p>(0.948, 1.897, 0)</p>
<p>(1, 2, 0)</p>
<h3>11. Beware filtering that reduces the range of a variable</h3>
<p>Some kinds of filtering can reduce the range of a variable – for example, instead of reaching zero, a variable may merely come <em>close</em> to zero. This is important in checks that assumes variables will come to have certain value <em>eventually – </em>these checks must be modified to compensate for the range discrepancies.</p>
<h3>12. Beware of accumulated latency when filtering variables through various layers of logic</h3>
<p>Filtering usually results in some latency. Where filtering is used in a layered system, these latencies can add up, and produce a system that is slow to respond. In many situations these latencies can be reduced or eliminated if you can make accurate predictions about the future.</p>
<p>You can reduce the filtering by using it only where it is really important – not everywhere. You can also exchange smoothness for a quicker response. How you accomplish this depends on the method of filtering you use; in the filtering described above you can increase the value of the increment.</p>
<p>If you feel adventurous, you can try out a system that filters only after it becomes aware that it is necessary. For example, the amount of filtering you apply can depend on the amount of noise measured over the last number of frames. In many situations you can approximate the amount of noise by the amount energy of the measured signal. Systems like these can be hard to make robust without resorting to difficult mathematics or special software.</p>
<p>You can also switch to a more sophisticated filtering approach, such as a Kalman filter or PID controller. PID controllers uses prediction to reduce latency; Kalman filtering uses a system model that makes it more effective in complicated scenarios.</p>
<h3>13. Be Careful When filtering combined signals</h3>
<p>You might want to add (or combine otherwise) several signals, filter this combination, and work on this filtered combined signal. This is a mistake when the signals have typical data transitions at different frequencies: ones signals noise is another&#8217;s data.</p>
<p>To illustrate the problem, look at the two signals below. Signal 1 is a low frequency signal, with a spike of noise. Signal 2 is a pure high frequency signal. The noise is clearly visible in the combined signal. Also shown are several filtered versions of the combined signal. Notice that the more we filter, the more we reduce the high frequency signal. And if we do not filter enough, the noise is still very present.</p>
<p>The solution is to filter the signals separately – the low frequency signal can be filtered much more than the high frequency signal – and only then combine the filtered sequences. The result is shown in the last figure.</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="166" valign="top"><span style="color: #408080;"> <img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="signal1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/signal1.png" border="0" alt="signal1" width="160" height="140" /> </span></td>
<td width="166" valign="top"><span style="color: #408080;"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="signal2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/signal2.png" border="0" alt="signal2" width="160" height="140" /> </span></td>
<td width="166" valign="top"><span style="color: #408080;"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="combined_signal" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/combined_signal.png" border="0" alt="combined_signal" width="160" height="140" /> </span></td>
</tr>
<tr>
<td width="166" valign="top"><span style="color: #408080;">Signal 1</span></td>
<td width="166" valign="top"><span style="color: #408080;">Signal 2</span></td>
<td width="166" valign="top"><span style="color: #408080;">Combined signal</span></td>
</tr>
<tr>
<td width="166" valign="top"><span style="color: #408080;"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="filtered_0_1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/filtered_0_1.png" border="0" alt="filtered_0_1" width="160" height="140" /></span></td>
<td width="166" valign="top"><span style="color: #408080;"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="filtered_0_5" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/filtered_0_5.png" border="0" alt="filtered_0_5" width="160" height="140" /> </span></td>
<td width="166" valign="top"><span style="color: #408080;"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="combined_signal" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/combined_signal1.png" border="0" alt="combined_signal" width="160" height="140" /> </span></td>
</tr>
<tr>
<td width="166" valign="top"><span style="color: #408080;">Combined signal filtered (0.1)</span></td>
<td width="166" valign="top"><span style="color: #408080;">Combined signal filtered (0.5)</span></td>
<td width="166" valign="top"><span style="color: #408080;">Combined signal filtered (1.0)</span></td>
</tr>
<tr>
<td width="166" valign="top"><span style="color: #408080;"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="filtered_separately" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/filtered_separately.png" border="0" alt="filtered_separately" width="160" height="140" /> </span></td>
<td width="166" valign="top"><span style="color: #408080;"> </span></td>
<td width="166" valign="top"><span style="color: #408080;"> </span></td>
</tr>
<tr>
<td width="166" valign="top"><span style="color: #408080;">Signals filtered before combined.</span></td>
<td width="166" valign="top"></td>
<td width="166" valign="top"></td>
</tr>
</tbody>
</table>
<h3>14. Avoid if-then logic in response calculations.</h3>
<p>If-then logic signifies one of two things:</p>
<ul>
<li>a state difference that should be implemented as proper discrete state of the state machine; or</li>
<li>the need for a step function.</li>
</ul>
<p>In the first case, your state should be broken up into two states, with proper transitions. A stimulus response agent is complex enough with you having to track trough various conditions to understand behaviour. Every state should have one response that depends continuously on the stimulus. Because state machines scale so badly, introducing more states is not very desirable either. There are of course several ways to organise states properly to alleviate the scaling problem, but this is the topic of another tutorial.</p>
<p>If your if-then logic is against the value of a variable (for example &#8216;if x &gt; 0&#8242;), you can replace it with an appropriately chosen step function. Using step functions instead of if-then logic simplifies the design, and can be replaced with drop-in “smooth” versions when it becomes evident that it is necessary.</p>
<h2>Testing and Debugging</h2>
<h3>15. Rendering the current state-machine state on screen.</h3>
<p>It is a small point, but often strange behaviour results not from incorrect response to stimulus, but from incorrect state transitions. When implementing your agent inside the game, having state transitions visible on screen will make that kind of bug that much easier to spot.</p>
<h3>16. Graph variables and their internal states on screen.</h3>
<p>Graphing variables (filtered and unfiltered) over time on screen will save you hours of debugging time. Whenever your agent does something funny, you can see at a glance if there are variables with unexpected values that could explain the agent&#8217;s actions, perhaps using the CAS prototype as a reference.</p>
<p>Unfortunately, this tip becomes less useful as the system gets more complex. Having twenty plots on your screen will do little to spot problems.</p>
<h3>17. Use unit tests to ensure correct implementation of formulas.</h3>
<p>Stimulus response agents are perfect candidates for unit testing, especially when using the CAS prototype as a reference implementation. Unit testing your assumptions about the system will ensure correctness, and will help to make you aware of changes that break the system early. It will also make it easier to change and optimise formulas, or change them with smoother or sharper versions. Having a constant reference against which you can tweak parameters also allows you to be daring and make aggressive changes.</p>
<h3>18. Use generators to mock the agent&#8217;s environment.</h3>
<p>A generator is a object that generates a sequence of values. Typically it has a getValue() method, which returns a different value every time it is called. Generators are very similar to iterators, except that they usually generate values on the fly, rather than pointing to members of a container (although reading values from a container is one valid way to generate values). Generators are often used to implement iterators.</p>
<p>To implement unit tests and CAS prototype, you need to mock various aspects of the game, the game world, and other agents. Using generators for this purpose makes mocking unbelievably easy and quick. Use generators to generate streams of</p>
<ul>
<li>elapsed times;</li>
<li>path angle deviations;</li>
</ul>
<ul>
<li>positions and velocities of other agents; and</li>
<li>state transitions.</li>
</ul>
<p>You can even mock parts of your agent to test sections in isolation. It helps if you build a library of generators and functions (response curves) that can be stacked together. You will do good to implement at least the following functions:</p>
<ul>
<li>step, line, and ramp;</li>
<li>clamped line and sigmoid (or atan);</li>
<li>cos, square, and saw tooth;</li>
<li>exponential and exponential decay;</li>
</ul>
<p>You should implement the following generators:</p>
<ul>
<li>a general generator that generates values from a function;</li>
<li>a constant generator;</li>
<li>a sum and product generator (generates the sum or product of two generators); and</li>
<li>generators that generate random values of various distributions.</li>
</ul>
<h2>Conclusion</h2>
<p>A complex stimulus response agent can be a challenge to design and implement properly; every approach has its set of headaches, and every solution brings other considerations to the table. Solving problems is just half the fun – <em>not</em> solving them is the other half!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F10%2F25%2Ftips-for-designing-and-implementing-a-stimulus-response-agent%2F&amp;linkname=Tips%20for%20Designing%20and%20Implementing%20a%20Stimulus%20Response%20Agent"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/Wb9V8Xusgg2WneydWhByF4QvtPQ/0/da"><img src="http://feedads.g.doubleclick.net/~a/Wb9V8Xusgg2WneydWhByF4QvtPQ/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Wb9V8Xusgg2WneydWhByF4QvtPQ/1/da"><img src="http://feedads.g.doubleclick.net/~a/Wb9V8Xusgg2WneydWhByF4QvtPQ/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/G9oUzj2Wfi0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/10/25/tips-for-designing-and-implementing-a-stimulus-response-agent/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/10/25/tips-for-designing-and-implementing-a-stimulus-response-agent/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=tips-for-designing-and-implementing-a-stimulus-response-agent</feedburner:origLink></item>
		<item>
		<title>Guerrilla Tool Development</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/qpaNqoDXw78/</link>
		<comments>http://code-spot.co.za/2009/10/24/guerrilla-tool-development/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 16:18:45 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[ai editor]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[level editor]]></category>
		<category><![CDATA[tool development]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=750</guid>
		<description><![CDATA[ Tools for editing game levels and AI for your own games are nice to have, but it is not always practical to implement these for small projects, nor is it affordable to buy them off-the-shelf or bundled with expensive middleware.
In the Dev.Mag article Guerrilla Tool Development, I give some ideas for getting some useful [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border-right: 0px; border-top: 0px; display: inline; margin: 0px 10px 0px 0px; border-left: 0px; border-bottom: 0px" title="guerrilla_tools" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/guerrilla_tools1.png" border="0" alt="guerrilla_tools" width="142" height="142" align="left" /> Tools for editing game levels and AI for your own games are nice to have, but it is not always practical to implement these for small projects, nor is it affordable to buy them off-the-shelf or bundled with expensive middleware.</p>
<p>In the Dev.Mag article <a href="http://www.devmag.org.za/articles/294-GUERRILLA-TOOL-DEVELOPMENT/">Guerrilla Tool Development</a>, I give some ideas for getting some useful tools on a tight budget. Check it out!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F10%2F24%2Fguerrilla-tool-development%2F&amp;linkname=Guerrilla%20Tool%20Development"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/xoQdqFjbl7U6nBMupS6eXunZmds/0/da"><img src="http://feedads.g.doubleclick.net/~a/xoQdqFjbl7U6nBMupS6eXunZmds/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/xoQdqFjbl7U6nBMupS6eXunZmds/1/da"><img src="http://feedads.g.doubleclick.net/~a/xoQdqFjbl7U6nBMupS6eXunZmds/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/qpaNqoDXw78" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/10/24/guerrilla-tool-development/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/10/24/guerrilla-tool-development/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=guerrilla-tool-development</feedburner:origLink></item>
		<item>
		<title>15 Steps to Implement a Neural Net</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/r2o4OvbYBvU/</link>
		<comments>http://code-spot.co.za/2009/10/08/15-steps-to-implemented-a-neural-net/#comments</comments>
		<pubDate>Thu, 08 Oct 2009 15:02:26 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[artificial intelligence]]></category>
		<category><![CDATA[Matlab]]></category>
		<category><![CDATA[neural network]]></category>
		<category><![CDATA[Octave]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[pattern recognition]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[sampling]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=655</guid>
		<description><![CDATA[
(Original image by Hljod.Huskona / CC BY-SA 2.0).
I used to hate neural nets. Mostly, I realise now, because I struggled to implement them correctly. Texts explaining the working of neural nets focus heavily on the mathematical mechanics, and this is good for theoretical understanding and correct usage. However, this approach is terrible for the poor implementer, neglecting [...]]]></description>
			<content:encoded><![CDATA[<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="neuron" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/neuron1.jpg" border="0" alt="neuron" width="500" height="332" /></p>
<p>(<a href="http://www.flickr.com/photos/lorelei-ranveig/2294885420/">Original image</a> by <a rel="cc:attributionURL" href="http://www.flickr.com/photos/lorelei-ranveig/">Hljod.Huskona</a> / <a rel="license" href="http://creativecommons.org/licenses/by-sa/2.0/">CC BY-SA 2.0</a>).</p>
<p>I used to hate neural nets. Mostly, I realise now, because I struggled to implement them correctly. Texts explaining the working of neural nets focus heavily on the mathematical mechanics, and this is good for theoretical understanding and correct usage. However, this approach is terrible for the poor implementer, neglecting many of the details that concern him or her.</p>
<p>This tutorial is an implementation guide. It is not an explanation of how or why neural nets work, or when they should or should not be used. This tutorial will tell you step by step how to implement a very basic neural network. It comes with a simple example problem, and I include several results that you can compare with those that you find.</p>
<p><span id="more-655"></span></p>
<p>I tried to make the design as straightforward as possible. The training algorithm is simple backpropagation. There are no hidden layers (I will treat that in an upcoming tutorial), no momentum, no adaptive learning rates, and no sophisticated stopping conditions. Those are, in a sense, easy to add once you have a working neural net against which you can benchmark more elaborate designs.</p>
<p>To keep the implementation simple, I did not bother with optimisation. This too can easily be addressed once a working neural net is in place against which you can verify correctness and measure performance improvements.</p>
<p>The brief introduction below is a very superficial explanation of a neural net; it is included mostly to establish terminology and help you map it to the concepts that are explained in more detail in other texts.</p>
<h2>Preliminary remarks and overview</h2>
<h3>What we are doing</h3>
<p>The problem we are trying to solve is this: we have some measurements (features of an object), and we have a good idea that these features might tell us in which class the object belongs. For example, if we are dealing with fruit, knowing the size, colour, and “roughness” of the skin, we might deduce which type the fruit is. Of course, we want a <em>program </em>for this.</p>
<p>Now in heaven, there is a function for exactly that task – we give the function the features, and it spits out the class.</p>
<p>Down here on earth, we are not so lucky (well, not for most problems anyway). So instead, we have to do with some approximation. A neural net is one possibility – there are also others. A neural net (one without any hidden layers) is parameterised by a weight matrix. Different problems in general have different weight matrices. To solve our problem, we need to find a suitable matrix.</p>
<p>If both our set of known samples and the problem itself are reasonable, we might expect to find such a matrix. But not directly – we have to use some kind of iterative scheme – we have to “train” our neural net. We use some of the known samples for this.</p>
<p>Behind the scenes, the weight matrix and the feature vector are combined using some matrix operations to give the output vector, which is converted to a class. The mathematical details of this can be found <a href="http://www.mth.kcl.ac.uk/courses/guide.pdf">elsewhere</a> (<a href="http://www.learnartificialneuralnetworks.com/backpropagation.html">more</a>).</p>
<p>After we have trained the neural net, we can use it in an application to classify objects that we may or may not have encountered before. Generally, the training and application programs are separate. The training program is the difficult part; most of the tutorial deals with training.</p>
<p>It is common to divide the known samples in three sets, called the training set, validation set, and test set, typically divided in the ratio 50%, 25%, and 25%. The training set is used to update the weights iteratively; the validation set is used to stop the training algorithm, and the test set is used to estimate how well our trained neural net will do in the wild.</p>
<p>Each iteration of the training algorithm is called, quite poetically, an <em>epoch</em>. Many different things affect the number of epochs we will need to train the neural net: the problem complexity, how we scale our updates, and how the weight matrix has been initialised.</p>
<p>We can control the speed with a parameter called the learning rate. In general, higher learning rate means faster learning (although, when it is set too high, the network might become unstable and not learn at all).</p>
<h3>Representation</h3>
<p>We usually represent the features (our measurements) as a vector of numbers, like this:</p>
<p>[0.01, 1.07, 3.60]</p>
<p>In cases of non-numeric values, we convert whatever we have to numbers with some scheme. For instance, when dealing with colours, we might want to use RGB values, or we might want to make a list of colours (red, yellow, green, etc.), assign a number to each of these labels, and use the corresponding number.</p>
<p>Classes, usually not being numbers, are similarly treated: we assign a number (often arbitrarily) to each class, and use that in our computations. For the actual training, however, we use an output vector. The output vector has a 1 in the position of the class number, and 0 everywhere else.</p>
<p>Thus, if we are dealing with three classes of fruit (apple, pear, banana), and number the classes 1, 2, and 3 respectively, we will have the following output vectors:</p>
<table border="0" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td width="135" valign="top"><strong>Class</strong></td>
<td width="142" valign="top"><strong>Class Number</strong></td>
<td width="121" valign="top"><strong>Output Vector</strong></td>
</tr>
<tr>
<td width="135" valign="top">Apple</td>
<td width="142" valign="top">1</td>
<td width="121" valign="top">1 0 0</td>
</tr>
<tr>
<td width="135" valign="top">Pear</td>
<td width="142" valign="top">2</td>
<td width="121" valign="top">0 1 0</td>
</tr>
<tr>
<td width="135" valign="top">Banana</td>
<td width="155" valign="top">3</td>
<td width="153" valign="top">0 0 1</td>
</tr>
</tbody>
</table>
<p>It is convenient to put all the inputs of a set together in a single matrix, where each row is a sample. Similarly, outputs and classes are also put into matrices, with input sample in a row (say row number <em>n</em>) corresponds to output sample in row <em>n</em>, and also the class in row <em>n</em>.</p>
<p>The implementation below makes use of high-level matrix operations. This avoids many of the errors that can creep in loop-dense code. The following table will give dimensions of all the matrixes involved; this will be helpful during implementation (especially for assert statements). The numbers are given in terms of the number of inputs (features) of the problem, the number of outputs.</p>
<table border="0" cellspacing="0" cellpadding="2" width="490">
<tbody>
<tr>
<td width="263" valign="top"><strong>Matrix</strong></td>
<td width="113" valign="top"><strong>Rows</strong></td>
<td width="112" valign="top"><strong>Columns</strong></td>
</tr>
<tr>
<td width="256" valign="top">input vector of a single sample</td>
<td width="117" valign="top">1</td>
<td width="115" valign="top">input_count</td>
</tr>
<tr>
<td width="251" valign="top">output vector of a single sample</td>
<td width="120" valign="top">1</td>
<td width="117" valign="top">output_count</td>
</tr>
<tr>
<td width="248" valign="top">class vector of a single sample</td>
<td width="122" valign="top">1</td>
<td width="119" valign="top">1</td>
</tr>
<tr>
<td width="245" valign="top">input matrix of training set</td>
<td width="124" valign="top">training_count</td>
<td width="120" valign="top">input_count</td>
</tr>
<tr>
<td width="243" valign="top">output matrix of training set</td>
<td width="125" valign="top">training_count</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">class vector of training set</td>
<td width="126" valign="top">training_count</td>
<td width="121" valign="top">1</td>
</tr>
<tr>
<td width="242" valign="top">bias vector of training set</td>
<td width="126" valign="top">training_count</td>
<td width="121" valign="top">1</td>
</tr>
<tr>
<td width="242" valign="top">net vector of single sample</td>
<td width="126" valign="top">1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">weights matrix</td>
<td width="126" valign="top">input_count + 1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">weights delta matrix</td>
<td width="126" valign="top">input_count + 1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">error vector</td>
<td width="126" valign="top">1</td>
<td width="121" valign="top">output_count</td>
</tr>
<tr>
<td width="242" valign="top">delta (sensitivity vector)</td>
<td width="126" valign="top">1</td>
<td width="121" valign="top">output_count</td>
</tr>
</tbody>
</table>
<h3>Overview</h3>
<p>The basic idea of the training algorithm is the following:</p>
<p>First we load in the data: the training samples, the validation samples, and the test samples.</p>
<p>Then we start to train: we run the backpropagation algorithm on random samples. After each iteration, we see how our network is doing so far (on the validation set), and then we decide whether to keep training or not.</p>
<p>After we stopped, we do a final evaluation of our network on the test set – this gives us an indication of whether the neural net will generalise well to samples not originally in the training set.</p>
<p>After we have found a weight matrix that we can live with, we cfan incorporate this in the application were we need the functionality.</p>
<p>The training program has x functions:</p>
<ul>
<li>train</li>
<li>load data</li>
<li>feed-forward</li>
<li>evaluate network</li>
<li>backpropagation</li>
<li>output to class</li>
<li>class to output</li>
<li>activation</li>
<li>activation derivative</li>
</ul>
<p>The application program uses these functions:</p>
<ul>
<li>feed-forward</li>
<li>output vector to class</li>
</ul>
<h2>Implementation</h2>
<h3>1. Gather the necessary libraries (or write them)</h3>
<p>You will need the following libraries:</p>
<ul>
<li>A library that supports matrix algebra; and</li>
<li>A library that plots graphs (x versus y).</li>
</ul>
<p>If you can’t find a matrix library for your implementation language, then you can write a simple library yourself. Since neural nets do not require matrix inverses or long chains of matrix products, you need not worry (much) about numerical stability, thus the implementation is straightforward.</p>
<p>The implementation needs to support the following matrix operations:</p>
<ul>
<li>matrix transposition;</li>
<li>matrix addition;</li>
<li>matrix multiplication with a scalar;</li>
<li>ordinary matrix multiplication;</li>
<li>Hadamard multiplication (component-wise multiplication);</li>
<li>Kronecker multiplication (only necessary for between row and column vectors); and</li>
<li>horizontal matrix concatenation.</li>
</ul>
<p>The first few operations are standard matrix operations, but you might be less familiar with the last three. (Also check out the Wikipedia article on <a href="http://en.wikipedia.org/wiki/Matrix_multiplication">matrix multiplication</a> – it covers all the types of multiplication mentioned here.)</p>
<p>Hadamard multiplication of matrices is defined for two matrices of equal dimensions. Each component of the new matrix is the product of corresponding components in the two multiplicands, that is:</p>
<pre>Z[i][j] = X[i][j] * Y[i][j]</pre>
<p>The Kronecker product of a row vector and column vector is defined as a matrix whose components are given by:</p>
<pre>Z[i][j] = X[0][i] * Y[j][0]</pre>
<p>It is possible to define the product for arbitrary matrices, but we don’t need it.</p>
<p>The horizontal concatenation combines two matrices with the same number of rows. For example, the matrices A and B below will be concatenated to form the new matrix C:<br />
<img src='http://s.wordpress.com/latex.php?latex=A%3D%5Cbegin%7Bpmatrix%7D10%20%26%203%5C%5C4%20%26%205%5Cend%7Bpmatrix%7D%2C%5C%3AB%3D%5Cbegin%7Bpmatrix%7D6%20%26%208%20%26%202%5C%5C3%261%2610%5Cend%7Bpmatrix%7D%2C%5C%3AC%3D%5Cbegin%7Bpmatrix%7D10%20%26%203%266%20%26%208%20%26%202%5C%5C4%20%26%205%26%203%20%261%2610%5Cend%7Bpmatrix%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='A=\begin{pmatrix}10 &amp; 3\\4 &amp; 5\end{pmatrix},\:B=\begin{pmatrix}6 &amp; 8 &amp; 2\\3&amp;1&amp;10\end{pmatrix},\:C=\begin{pmatrix}10 &amp; 3&amp;6 &amp; 8 &amp; 2\\4 &amp; 5&amp; 3 &amp;1&amp;10\end{pmatrix}' title='A=\begin{pmatrix}10 &amp; 3\\4 &amp; 5\end{pmatrix},\:B=\begin{pmatrix}6 &amp; 8 &amp; 2\\3&amp;1&amp;10\end{pmatrix},\:C=\begin{pmatrix}10 &amp; 3&amp;6 &amp; 8 &amp; 2\\4 &amp; 5&amp; 3 &amp;1&amp;10\end{pmatrix}' class='latex' /></p>
<p>A simple implementation simply constructs a new matrix whose components are given by</p>
<pre>if j &lt; X_width
  Z[i][j] = X[i][j]
else
   Z[i][j] = Y[i, j – X_width]</pre>
<p>If no graph libraries are available, simply write a function that will output a tab-separated list of the input and output sequences to plot. You can then load or paste this into your favourite spreadsheet program to make the necessary plots.</p>
<h3>2. Implement Output and Class conversion functions</h3>
<p>This is very simple: implement a function that converts an output matrix to a class number vector, and another that converts a class number to an output vector.</p>
<p>For example, the output_to_class function will take the following matrix</p>
<p>1 0 0</p>
<p>0 1 0</p>
<p>0 0 1</p>
<p>1 0 0</p>
<p>0 0 1</p>
<p>and convert it to:</p>
<p>1</p>
<p>2</p>
<p>3</p>
<p>1</p>
<p>3</p>
<p>(The second function will convert the second matrix back to the first matrix).</p>
<h3>3. Implement a function to read in data files</h3>
<p>For this tutorial you can use the following three files:</p>
<ul>
<li>iris_training.dat</li>
<li>iris_validation.dat</li>
<li>iris_test.dat</li>
</ul>
<p>These three files contain samples from the <a href="http://en.wikipedia.org/wiki/Iris_flower_data_set">ICU iris dataset</a>, a simple and quite famous dataset. In each file, samples or contained in rows. Each row has seven entries, separated by tabs. The first four entries are features of irises (sepal length, sepal width, petal length, and petal width); the last three is the outputs denoting the species of iris (setosa, versicolor, and virginica). I have preprocessed the values a bit to get them in the appropriate ranges.</p>
<p>You must read in the data so that you can treat the inputs of each set as a single matrix; similarly for the outputs.</p>
<p>I find it useful to store all the data in a structure, like this:</p>
<ul>
<li>data_set
<ul>
<li>input_count</li>
<li>output_count</li>
<li>training_set
<ul>
<li>inputs</li>
<li>outputs</li>
<li>classes</li>
<li>count</li>
<li>bias</li>
</ul>
</li>
<li>validation_set
<ul>
<li>inputs</li>
<li>outputs</li>
<li>classes</li>
<li>count</li>
<li>bias</li>
</ul>
</li>
<li>test_set
<ul>
<li>inputs</li>
<li>outputs</li>
<li>classes</li>
<li>count</li>
<li>bias</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>This makes it more useful to send the data as parameters.</p>
<h3>4. Implement an activation function and its derivative</h3>
<p>The activation function must take in a matrix X, and return a matrix Y. Y is computed by applying a function component-wise to X. For now, use the hyperbolic tangent function:</p>
<img src='http://s.wordpress.com/latex.php?latex=%20f%28x%29%20%3D%20%5Cdfrac%7B%5Ctanh%28x%29%20%2B%201%7D%7B2%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' f(x) = \dfrac{\tanh(x) + 1}{2}' title=' f(x) = \dfrac{\tanh(x) + 1}{2}' class='latex' /><br />
The activation function derivative must similarly take in a matrix X, and return a matrix Y. Y is computed by applying the derivative of the activation componentwise to X. The derivative of the function above is:<br />
<img src='http://s.wordpress.com/latex.php?latex=f%27%28x%29%20%3D%20%5Cdfrac%7B1%20-%20%5Ctanh%5E2%28x%29%7D%7B2%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='f&#039;(x) = \dfrac{1 - \tanh^2(x)}{2}' title='f&#039;(x) = \dfrac{1 - \tanh^2(x)}{2}' class='latex' /></p>
<h3>5. Implement the feed-forward function</h3>
<p>The function must take as arguments an input matrix, weight matrix, and a bias node matrix.</p>
<p>The function should return an output matrix, and a net matrix</p>
<p>These are computed as follows:</p>
<pre>net = mul(weights, horcat(inputs, bias))
output = activate(net)</pre>
<p>The bias matrix is a constant column vector of 1s with as many rows as the input matrix. This vector corresponds to the bias nodes. The implementation here is a bit clumsy, but for now, the approach used here minimises the potential for error.</p>
<h3>6. Implement a weight initialisation function</h3>
<p>This function must take in a maximum weight, a width and height, and return a matrix of the given width and height, randomly initialised in the range [-max_weight max_weight].
<h3>7. Implement a function that evaluates the network error.</h3>
<p>The function must take in:</p>
<ul>
<li>an input matrix,</li>
<li>a weight matrix,</li>
<li>a target output matrix,</li>
<li>a target class matrix,</li>
<li>a bias matrix.</li>
</ul>
<p>The function must return the error e, and the classification error c.</p>
<p>To compute these, first compute the output matrix Z using the feed-forward function (you can ignore the net matrix).</p>
<pre>[output net] = feedforward(inputs, weights, bias)</pre>
<p>Now subtract the target output matrix from the output matrix, square the components, add together, and normalise:</p>
<pre>error = sum_all_components((target_outputs – outputs)^2) ...</pre>
<pre>   / (sample_count * output_count)</pre>
<p>From the output matrix, calculate the classes:</p>
<pre>classes = classes_from_output_vectors(outputs)</pre>
<p>Count the number of classes that corresponds with the target classes, and divide by the number of samples to normalise:</p>
<pre>c = sum_all_components(classes != target_classes)/sample_count</pre>
<p>(Here, our inequality returns a matrix of 0s and 1s, with 1s in positions where the corresponding components in classes and target_classes are not equal.)</p>
<h3>8. Implement a dummy backpropagation function</h3>
<p>The function should take in:</p>
<ul>
<li>An input matrix</li>
<li>A weight matrix</li>
<li>a learning rate (eta, as in the Greek letter)</li>
<li>a bias vector</li>
</ul>
<p>The function must return an updated weight matrix. For now, return W as is.</p>
<h3>9. Implement the train function</h3>
<p>The training function should take in three sets, the training_set, validation_set, and test_set. Implement a way to limit the maximum number of samples that will actually be used for training (you can also do his in the main program described in the next section). This is very helpful for debugging purposes (especially if you plan to later replace the backpropagation algorithm with something a little faster – and more complicated).</p>
<p>The function should return a weight matrix, and error values as floats.</p>
<p>Initialise a value plot_graphs to true. This is a debug flag, so it is appropriate to implement this as a macro if it is supported by the implementation language.</p>
<p>The function should initialise a weight matrix using initialise weights. For now, use a max_weight of 1/2.</p>
<p>The function should also construct three bias vectors bias_training, bias_validate, and bias_test. Each must contain only 1s, with as many rows as there are inputs in the training, validation and test sets respectively.</p>
<p>Implement a while loop that stops after 500 iterations. (We will change the while condition later to something else, so do not use a for loop).</p>
<p>Inside the loop, call the backpropagation algorithm. Use the training set inputs, the weights, (for now) a fixed learning rate of 0.1, and bias vector bias_train. Assign the result to weights.</p>
<p>Still inside the loop, call the network error function three times: one time for each of the training, validation, and test sets. Use the weight matrix, and the appropriate bias vector. Wrap these calls in an if-statement that tests for a value plot_graphs. (If your language supports it, you can use conditional compilation on the value of plot_graphs).</p>
<p>Store the errors in six arrays (error_train, classification_error_train, etc.), with the current epoch number as index.</p>
<p>After the loop, plot the six error arrays as a function of epoch number. Wrap this in an if-statement (or conditional compilation statement) that tests for the value plot_graphs.</p>
<p>Call the network error function again, on all three sets as before.</p>
<p>Return the weights, and the six errors.</p>
<h3>10. Implement the main training program</h3>
<p>The program should load in the sets (using the load_sets function), and pass these to the training algorithm.</p>
<h3>11. Run the program</h3>
<p>The important thing is that everything should run. You should see your error plots; at this stage they should be straight, horizontal lines. Because of the random weight initialisation, we cannot predict where these lines will lie (so do not be alarmed if they do not look exactly the same as below – as long as they are straight and horizontal).</p>
<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="backprop" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/backprop.png" border="0" alt="backprop" width="486" height="399" /></p>
<h3>12. Implement the backpropagation function</h3>
<p>You have already created the dummy function; now you can put in the actual calculations.</p>
<p>First, select a random sample.</p>
<p>Now, calculate the net matrix and output matrix using the feed-forward function.</p>
<pre>[output, net] = feedforward(random_sample, weights, bias)</pre>
<p>Calculate the error vector</p>
<pre>error_vector = target_outputs - outputs</pre>
<p>Calculate the sensitivity.</p>
<pre>delta = hammard(error_vector, activation_diff(net))</pre>
<p>The corresponding mathematical expression in the textbook might look like this:<br />
<img src='http://s.wordpress.com/latex.php?latex=%5Cdelta_k%20%3D%20%28t_k%20-%20z_k%29%20f%27%28y_k%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='\delta_k = (t_k - z_k) f&#039;(y_k)' title='\delta_k = (t_k - z_k) f&#039;(y_k)' class='latex' /></p>
<p>Calculate the weights delta:</p>
<pre>weights_delta = scalar_mul(eta, kronecker(transpose(outputs), delta))</pre>
<p>The corresponding mathematical expression in the textbook might look like this:<br />
<img src='http://s.wordpress.com/latex.php?latex=w_%7Bkj%7D%20%3D%20%5Ceta%20%28t_k%20-%20z_k%29%20f%27%28y_k%29y_j&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='w_{kj} = \eta (t_k - z_k) f&#039;(y_k)y_j' title='w_{kj} = \eta (t_k - z_k) f&#039;(y_k)y_j' class='latex' /></p>
<p>Update the weights:</p>
<pre>weights = add(weights, weights_delta)</pre>
<p>and return the matrix.</p>
<h3>13 Run the program (AGAIN)</h3>
<p>First, set the debug option to train on only one sample. The curve should like like this:</p>
<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="backprop3" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/backprop3.png" border="0" alt="backprop3" width="486" height="398" /></p>
<p>Notice that the error curves are smooth, the training error rate goes to 0, and the other error rates go to 0.4, plus or minus – this depends on the initial weights. It will also be different if you use a sample other than the first.</p>
<p>If your curve looks right, change the debug option to train on all samples. Your error curves should now look something like this:</p>
<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="backprop2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/10/backprop2.png" border="0" alt="backprop2" width="486" height="398" /></p>
<p>The important feature of the error curves is that they should steadily descent on average. If your curve does not resemble the one shown here; there is a mistake in your implementation. It is often helpful to limit the training set to a single sample (thereby eliminating the randomisation of sampling during training) to see what is going on.</p>
<p>Although the errors often follow the relationship training &lt; validation &lt; test, this is not always the case, so do not be alarmed if this is not true on a run (You can see it is not always true in the run above).</p>
<h3>14 Implement a proper stopping condition</h3>
<p>Change the while loop to stop when the validation error drops below a threshold. Note that this threshold usually depends on the problem. There are better stopping conditions that are less sensitive to the problem at hand, but this one will do for now.</p>
<h3>15 Implement a statistical analysis</h3>
<p>This part is important for you to get an idea of the robustness of the neural net. In practice, a very simple analysis will suffice.</p>
<p>This part need to train the algorithm 30 times, and then report the mean, standard deviation and maximum of the</p>
<ul>
<li>training time,</li>
<li>regression error, and</li>
<li>classification error (on the test sets).</li>
</ul>
<p>In general, you would like all these values to be “low”. Here are some experiments for the iris data set with different learning rates. For each, 30 runs were made; other parameters are as described earlier (max_weight = 1/2, validation_stop_threshold = 0.1).</p>
<table border="0" cellspacing="0" cellpadding="2" width="486">
<tbody>
<tr>
<td width="171" valign="top"></td>
<td width="107" valign="top"><strong>Mean</strong></td>
<td width="100" valign="top"><strong>Standard Deviation</strong></td>
<td width="106" valign="top"><strong>Maximum</strong></td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 0.05</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">1200</td>
<td width="100" valign="top">124.681</td>
<td width="106" valign="top">1489</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.115343</td>
<td width="100" valign="top">0.0017233</td>
<td width="106" valign="top">0.11894</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.17807</td>
<td width="100" valign="top">0.0456762</td>
<td width="106" valign="top">0.263158</td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 0.1</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">582.533</td>
<td width="100" valign="top">65.3076</td>
<td width="106" valign="top">719</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.114626</td>
<td width="100" valign="top">0.00180851</td>
<td width="106" valign="top">0.118697</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.214912</td>
<td width="100" valign="top">0.0317323</td>
<td width="106" valign="top">0.263158</td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 0.5</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">120.967</td>
<td width="100" valign="top">16.7095</td>
<td width="106" valign="top">169</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.115711</td>
<td width="100" valign="top">0.0038786</td>
<td width="106" valign="top">0.123573</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.245614</td>
<td width="100" valign="top">0.0242702</td>
<td width="106" valign="top">0.263158</td>
</tr>
<tr>
<td width="171" valign="top"><strong>eta = 1</strong></td>
<td width="107" valign="top"></td>
<td width="100" valign="top"></td>
<td width="106" valign="top"></td>
</tr>
<tr>
<td width="171" valign="top">Training time</td>
<td width="107" valign="top">67.1667</td>
<td width="100" valign="top">12.2477</td>
<td width="106" valign="top">99</td>
</tr>
<tr>
<td width="171" valign="top">Regression error</td>
<td width="107" valign="top">0.114755</td>
<td width="100" valign="top">0.00488566</td>
<td width="106" valign="top">0.124468</td>
</tr>
<tr>
<td width="171" valign="top">Classification Error</td>
<td width="107" valign="top">0.253509</td>
<td width="100" valign="top">0.0201287</td>
<td width="106" valign="top">0.263158</td>
</tr>
</tbody>
</table>
<h2>Using the neural net in a program</h2>
<p>To use the neural net in a program after you have trained it, you need to save the weights found by the training program to a file. Your application must then read in this weights, and use it with the feedforward function to calculate the class.</p>
<p>Here is pseudo-code for the program. Note that the training program and classification program needn’t be implemented in the same language. This allows you to take advantage of speed and interface components that might not be available in your target platform. It is a very good idea to implement your training algorithm on a computer algebra system (such as <a href="http://www.mathworks.com/">Matlab</a> or <a href="http://www.gnu.org/software/octave/">Octave</a>) where you can take advantage of both matrix and graphing capabilities (the code provided below works in both).</p>
<h2>Using the training algorithm on other problems</h2>
<p>When using your neural net for other algorithms, you might need to change the learning rate, stopping threshold, and weight_max for weight the initialisation. The error plots are indispensible for this purpose.</p>
<p>As long as the learning rate is not too high, it should not affect the quality of the solution, only the number of iterations necessary to obtain it. The stopping threshold, however, has does affect the quality of the solution: if it is tool low, the problem might not be solved, or the neural net might train very long; if it is too high, you will get poor performance. There are better stopping conditions available; once you have everything working, you should investigate these.</p>
<p>Remember that you should not base your decisions on a single run, as runs can differ quite drastically from one another. Perform a few runs, and base decisions on these.</p>
<p>The value weight_max can usually be chosen as 1/sqrt(input_count) with good results, but here too it depends on the problem.</p>
<p>For further benchmarking, check out the <a href="ftp://ftp.ira.uka.de/pub/neuron/">Proben1 datasets</a>, described <a href="http://page.mi.fu-berlin.de/prechelt/Biblio/1994-21.pdf">here</a>. (Also check out the erratum note on <a href="http://page.mi.fu-berlin.de/prechelt/Biblio/">this site</a> – search for proben on the page.)</p>
<h2>Download</h2>
<p>The following code works in Matlab and Octave. (Included is a randint function; if you are using Matlab you can remove it, because it is already implemented in Matlab).</p>
<p><a href="http://www.code-spot.co.za/downloads/neural_net/iris_data_files.zip">iris_data_files.zip</a> (3 KB)</p>
<p><a href="http://www.code-spot.co.za/downloads/neural_net/basic_neural_net_0_1.zip">basic_neural_net_0_1.zip</a> (10 KB)</p>
<p>The program provided cheats a little – instead of reading in the raw .dat files, it reads in the .mat file that already has the data in the right structure.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F10%2F08%2F15-steps-to-implemented-a-neural-net%2F&amp;linkname=15%20Steps%20to%20Implement%20a%20Neural%20Net"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/2joDjALDj9axjCzE6xhS8Y-cl8o/0/da"><img src="http://feedads.g.doubleclick.net/~a/2joDjALDj9axjCzE6xhS8Y-cl8o/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/2joDjALDj9axjCzE6xhS8Y-cl8o/1/da"><img src="http://feedads.g.doubleclick.net/~a/2joDjALDj9axjCzE6xhS8Y-cl8o/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/r2o4OvbYBvU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/10/08/15-steps-to-implemented-a-neural-net/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/10/08/15-steps-to-implemented-a-neural-net/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=15-steps-to-implemented-a-neural-net</feedburner:origLink></item>
		<item>
		<title>Getting More out of Seamless Tiles</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/Gl7bZeVvnIc/</link>
		<comments>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/#comments</comments>
		<pubDate>Thu, 28 May 2009 08:46:07 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[blending]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[grids]]></category>
		<category><![CDATA[tiles]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=620</guid>
		<description><![CDATA[I wrote an article for Dev.Mag covering some techniques for working with seamless tile sets such as making blend tiles, getting more variety with procedural colour  manipulation, tile placement strategies, and so on. 
Check it out!
The Python Image Code has also been updated with some of the algorithms explained in the article.
]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-622" title="tiles_header_small" src="http://code-spot.co.za/blog/wp-content/uploads/2009/05/tiles_header_small.png" alt="tiles_header_small" width="142" height="142" />I wrote an article for Dev.Mag covering <a href="http://www.devmag.org.za/articles/70-GETTING-MORE-OUT-OF-SEAMLESS-TILES/">some techniques for working with seamless tile sets</a> such as making blend tiles, getting more variety with procedural colour  manipulation, tile placement strategies, and so on. </p>
<p>Check it out!</p>
<p>The <a href="http://code-spot.co.za/python-image-code/">Python Image Code</a> has also been updated with some of the algorithms explained in the article.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F05%2F28%2Fgetting-more-out-of-seamless-tiles%2F&amp;linkname=Getting%20More%20out%20of%20Seamless%20Tiles"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/l1tbSmPKw50awA0YRqSJIwM39rs/0/da"><img src="http://feedads.g.doubleclick.net/~a/l1tbSmPKw50awA0YRqSJIwM39rs/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/l1tbSmPKw50awA0YRqSJIwM39rs/1/da"><img src="http://feedads.g.doubleclick.net/~a/l1tbSmPKw50awA0YRqSJIwM39rs/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/Gl7bZeVvnIc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=getting-more-out-of-seamless-tiles</feedburner:origLink></item>
		<item>
		<title>How to Turn XSI Mod Tool into a Level Editor for your XNA Games: Example Updated for XNA 3.0.</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/cMeEeZoUi1o/</link>
		<comments>http://code-spot.co.za/2009/05/27/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-example-updated-for-xna-30/#comments</comments>
		<pubDate>Wed, 27 May 2009 12:08:41 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[art pipeline]]></category>
		<category><![CDATA[editor]]></category>
		<category><![CDATA[game tools]]></category>
		<category><![CDATA[level editor]]></category>
		<category><![CDATA[XNA]]></category>
		<category><![CDATA[XSI Mod Tool]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=593</guid>
		<description><![CDATA[The example for the tutorial How to Turn XSI Mod Tool into a Level Editor for your XNA Games: Updated for XNA 3.0 have also been updated to work with XNA 3.0. The XSI plug-in has also been tested in the new Mod Tool (7.5).
Download
XSIModToolLevelEditor3.zip (5.2 MB).
]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-595 alignleft" title="xsixna_small_header1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/05/xsixna_small_header1.png" alt="xsixna_small_header1" width="142" height="142" />The example for the tutorial <a href="http://code-spot.co.za/2009/04/08/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-updated-for-xna-30/">How to Turn XSI Mod Tool into a Level Editor for your XNA Games: Updated for XNA 3.0</a> have also been updated to work with XNA 3.0. The XSI plug-in has also been tested in the new Mod Tool (7.5).</p>
<h2>Download</h2>
<p><a href="http://www.code-spot.co.za/downloads/tutorials/XSIModToolLevelEditor3.zip">XSIModToolLevelEditor3.zip (5.2 MB)</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F05%2F27%2Fhow-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-example-updated-for-xna-30%2F&amp;linkname=How%20to%20Turn%20XSI%20Mod%20Tool%20into%20a%20Level%20Editor%20for%20your%20XNA%20Games%3A%20Example%20Updated%20for%20XNA%203.0."><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/qe8fqpKN888LeaZHJpJuVT7Tjgc/0/da"><img src="http://feedads.g.doubleclick.net/~a/qe8fqpKN888LeaZHJpJuVT7Tjgc/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/qe8fqpKN888LeaZHJpJuVT7Tjgc/1/da"><img src="http://feedads.g.doubleclick.net/~a/qe8fqpKN888LeaZHJpJuVT7Tjgc/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/cMeEeZoUi1o" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/05/27/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-example-updated-for-xna-30/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/05/27/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-example-updated-for-xna-30/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-example-updated-for-xna-30</feedburner:origLink></item>
		<item>
		<title>Update: Reference for Functional Equations</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/9-3mh_1eMmY/</link>
		<comments>http://code-spot.co.za/2009/05/27/update-reference-for-functional-equations/#comments</comments>
		<pubDate>Wed, 27 May 2009 08:11:32 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[binomial transform]]></category>
		<category><![CDATA[functional equation]]></category>
		<category><![CDATA[functional equations]]></category>
		<category><![CDATA[z-transform]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=609</guid>
		<description><![CDATA[In this new  version of Reference for Functional Equations I added several more z-transform pairs. I also started to add binomial transform pairs. The definition for the binomial is not consistent among different authors. I arbitrarily chose one, and later I changed it. I will probably change it again. Several typos were fixed. I am working on [...]]]></description>
			<content:encoded><![CDATA[<p><img class="size-full wp-image-421 alignleft" title="1052727062_0ec2c67ea4_small" src="http://code-spot.co.za/blog/wp-content/uploads/2009/02/1052727062_0ec2c67ea4_small.jpg" alt="1052727062_0ec2c67ea4_small" width="142" height="142" />In this new  version of <a href="http://code-spot.co.za/difference-and-functional-equations-reference/">Reference for Functional Equations</a> I added several more z-transform pairs. I also started to add binomial transform pairs. The definition for the binomial is not consistent among different authors. I arbitrarily chose one, and later I changed it. I will probably change it again. Several typos were fixed. I am working on a system to include proofs so that the tables can be checked more easily.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F05%2F27%2Fupdate-reference-for-functional-equations%2F&amp;linkname=Update%3A%20Reference%20for%20Functional%20Equations"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/qa_DiE0gLgVjsPDSI6BZ1NdlEt8/0/da"><img src="http://feedads.g.doubleclick.net/~a/qa_DiE0gLgVjsPDSI6BZ1NdlEt8/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/qa_DiE0gLgVjsPDSI6BZ1NdlEt8/1/da"><img src="http://feedads.g.doubleclick.net/~a/qa_DiE0gLgVjsPDSI6BZ1NdlEt8/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/9-3mh_1eMmY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/05/27/update-reference-for-functional-equations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/05/27/update-reference-for-functional-equations/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=update-reference-for-functional-equations</feedburner:origLink></item>
		<item>
		<title>Generating Random Integers With Arbitrary Probabilities</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/3ZP8x3yXLLg/</link>
		<comments>http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 07:12:28 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[probability]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[random distribution]]></category>
		<category><![CDATA[random integer]]></category>
		<category><![CDATA[random number generation]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=582</guid>
		<description><![CDATA[
I finally laid my hands on Donald Knuth’s The Art of Computer Programming (what a wonderful set of books!), and found a neat algorithm for generating random integers 0, 1, 2, … , n – 1, with probabilities p_0, p_1, … , p_(n-1).
I have written about generating random numbers (floats) with arbitrary distributions for one [...]]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline" title="header" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/header2.png" alt="header" width="500" height="332" /></p>
<p>I finally laid my hands on Donald Knuth’s <em><a href="http://www.amazon.com/Art-Computer-Programming-Volumes-Boxed/dp/0201485419">The Art of Computer Programming</a></em> (what a wonderful set of books!), and found a neat algorithm for generating random integers 0, 1, 2, … , n – 1, with probabilities p_0, p_1, … , p_(n-1).</p>
<p>I have written about generating random numbers (floats) with arbitrary distributions for <a href="http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/">one dimension</a> and <a href="http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/">higher dimensions</a>, and indeed that method can be adapted for generating integers with specific probabilities. However, the method described below is much more concise, and efficient (I would guess) for this special case. Moreover, it is also easy to adapt it to generate floats for continuous distributions.</p>
<p><span id="more-582"></span></p>
<h2>Description of the Algorithm</h2>
<p>The basic idea of the algorithm is simple. We have two tables of length n that contains integers (K, L), and a third table that contains probabilities (P). The first table merely contains the integers 0 to n-1 (thus, we need not actually store it explicitly). The other two tables are computed before generation (more about that below).</p>
<p>To generate a random number, we generate a random integer (uniformly distributed between 0 and n-1 inclusive), and a random float (uniformly distributed between 0 and 1). The integer tells us which cells in the table to use. First we lookup the probability in P at that index. If the float is smaller than that value, we return the integer in K, otherwise we return the integer in L. (Note, the integer in K is exactly the random integer itself. Therefore, we do not actually have a table K – we simply use the random integer.)</p>
<p>Now this will only give the desired result if the tables have been constructed for this to work. Before looking at how these tables are generated, let us look at a very simple example. Suppose we want to generate 0, 1, 2, with probabilities 3/18, 7/18, 8/18. Can you see why the following tables will work?</p>
<table border="0" cellspacing="0" cellpadding="0" width="500">
<tbody>
<tr>
<td width="125" valign="top"></td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">2</td>
</tr>
<tr>
<td width="125" valign="top">P</td>
<td width="125" valign="top">1/2</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">5/6</td>
</tr>
<tr>
<td width="125" valign="top">L</td>
<td width="125" valign="top">2</td>
<td width="125" valign="top">*</td>
<td width="125" valign="top">1</td>
</tr>
</tbody>
</table>
<p>There is only one way to generate 0: if the random integer is 0, and the random float is below 1/2. This will happen with probability 1/3 x 1/2 = 1/6 = 3/18.</p>
<p>There are two ways of generating 1:</p>
<ul>
<li>if the random integer is 1 (probability 1/3 = 6/18); or</li>
<li>if the random integer is 2, and the float is above 5/6 (probability 1/3 x 1/6 = 1/18).</li>
</ul>
<p>Adding these probabilities, we get 6/18 + 1/18 = 7/18.</p>
<p>There are also two ways to generate 2:</p>
<ul>
<li>if the random integer is 0 and the random float is above 1/2 (1/3 x 1/2 = 1/6 = 3/18); or</li>
<li>if the random integer is 2 and the random float is below 5/6 (1/3 x 5/6 = 5/18).</li>
</ul>
<p>Adding these probabilities, we get 3/18 + 5/18 = 8/18.</p>
<h2>Generating the tables</h2>
<p>Consider this problem:</p>
<ul>
<li>We have n<em> </em>squares that we want to paint.</li>
<li>We have five colours of paint, possibly different amounts of paint for each colour.</li>
<li>Each square has a border in one of the colours; no two borders are the same colour.</li>
<li>In total, there is just enough paint to cover the n squares <em>exactly</em>.</li>
<li>We want to paint each square with at most two colours, with one colour matching the border.</li>
</ul>
<p>To do this, we sort the paint buckets in ascending order. We paint the square that matches the first bucket with the first bucket, and whatever remains with the last bucket. The first bucket is empty (why?), and there might be some paint remaining in the last bucket. We now put this bucket back so that the buckets are sorted according to the new quantities of paint. The first square is completely covered (why?). Note that the painted square’s colour corresponds with the depleted colour.</p>
<p>The situation is now: we have n-1 unpainted squares, and n-1 colours of paint. This is the same problem as the initial problem, with one less square and one less colour. Therefore, we proceed as before, and repeat this process until all the squares have been painted and all the paint has been used.</p>
<p>To answer the two <em>why</em>’s above:</p>
<p>The first bucket is always empty, because the smallest bucket cannot cover more than one square. Since it is the smallest bucket, all other buckets must contain at least as much paint. Thus, we have n colours, and enough paint of each colour to paint more than one square. Thus, in total, we must have more paint than is required to paint n squares. But we said that we have <em>exactly</em> the right amount of paint needed, not more. Therefore, the smallest amount of paint cannot cover more than one square.</p>
<p>The first square is always covered completely, since the last bucket always contains enough paint for at least one square. If it did not, since it is the largest bucket, all other buckets will paint less than one square. In total, we would have n colours, each that can cover less than one square. Thus, all our paint will cover less than n squares: we do not have enough paint. But we said that we <em>do</em>, so this cannot be. Therefore, we must have enough paint in the last bucket to cover at least one square.</p>
<p>Below is an illustration of this process for three colours. Here we assume that 1 litre of paint covers 1 square. We have 1/3 = 3/6 litre of red, 7/6 litre of green, and 8/6 litre of cyan.</p>
<h3>Sort Paint</h3>
<p><img style="display: inline" title="step0" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step0.png" alt="step0" width="500" height="92" /></p>
<h3>Paint from first bucket</h3>
<p><img style="display: inline" title="step1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step1.png" alt="step1" width="500" height="92" /></p>
<h3>Paint from last bucket</h3>
<p><img style="display: inline" title="step2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step2.png" alt="step2" width="500" height="92" /></p>
<h3>Sort Paint</h3>
<p><img style="display: inline" title="step3" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step3.png" alt="step3" width="399" height="92" /></p>
<h3>Paint from first bucket</h3>
<p><img style="display: inline" title="step4" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step4.png" alt="step4" width="396" height="92" /></p>
<h3>Paint from last bucket</h3>
<p><img style="display: inline" title="step5" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step5.png" alt="step5" width="396" height="110" /></p>
<h3>Sort paint</h3>
<p><img style="display: inline" title="step6" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step6.png" alt="step6" width="299" height="110" /></p>
<h3>Paint from first bucket</h3>
<p><img style="display: inline" title="step7" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/step7.png" alt="step7" width="291" height="110" /></p>
<p>As you can see, the solution above corresponds with the tables given in the example above. Indeed, the algorithm for calculating the tables is exactly the same as the paint algorithm:</p>
<ul>
<li>The n colours correspond to the n integers (from 0 to n-1) that we want to generate.</li>
<li>The initial amounts of paints corresponds with the (relative) probabilities that we want to generate each integer.</li>
<li>The amount of paint used to paint a square of the same border is the entry in table P – the probability of using the number associated with that cell (i.e., “the border”).</li>
<li>The other colour used to paint a square (if any) corresponds to the entry in table K.</li>
</ul>
<h2>A Small Optimisation in the Implementation</h2>
<h3>Generating two uniform random numbers for the price of one</h3>
<p>There is a trick to generate a random integer (0 &lt;= n &lt; k) and a random float (0 &lt;= x &lt; 1) from a single random float (0 &lt;= u &lt; 1) that is used in the implementation of this algorithm (see download below).</p>
<p>The trick is:</p>
<ul>
<li>n = floor (uk)</li>
<li>x = uk – n</li>
</ul>
<p>This assumes things about the random generator and the accuracy required. (I do not want to get into the details here).</p>
<h2>Download</h2>
<p>A python implementation of the above algorithm.</p>
<p><a href="http://www.code-spot.co.za/downloads/python/non_uniform_random_int.py">non_uniform_random_int.py</a></p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F04%2F28%2Fgenerating-random-integers-with-arbitrary-probabilities%2F&amp;linkname=Generating%20Random%20Integers%20With%20Arbitrary%20Probabilities"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/HnwzS9Xch1XchMeCkB6xhFOmo-M/0/da"><img src="http://feedads.g.doubleclick.net/~a/HnwzS9Xch1XchMeCkB6xhFOmo-M/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/HnwzS9Xch1XchMeCkB6xhFOmo-M/1/da"><img src="http://feedads.g.doubleclick.net/~a/HnwzS9Xch1XchMeCkB6xhFOmo-M/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/3ZP8x3yXLLg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/04/28/generating-random-integers-with-arbitrary-probabilities/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=generating-random-integers-with-arbitrary-probabilities</feedburner:origLink></item>
		<item>
		<title>Estimating a Continuous Distribution from a Sample Set</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/EakD68wdqEM/</link>
		<comments>http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 14:27:06 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[convolution]]></category>
		<category><![CDATA[distribution estimation]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[random distribution]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=445</guid>
		<description><![CDATA[ It is sometimes necessary to find the distribution given a sample set from that distribution. If we do not know anything about the distribution, we cannot recover it exactly, so here we look at ways of finding a (discrete) approximation.

I will cover the case for 2D sets here, but the ideas are easily extended [...]]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline" title="header_rand_dist2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/header-rand-dist2.png" alt="header_rand_dist2" width="500" height="374" /> It is sometimes necessary to find the distribution given a sample set from that distribution. If we do not know anything about the distribution, we cannot recover it exactly, so here we look at ways of finding a (discrete) approximation.</p>
<p><span id="more-445"></span></p>
<p>I will cover the case for 2D sets here, but the ideas are easily extended to any dimension.</p>
<h2>Visual Inspection From a Scatter Plot</h2>
<p>The easy way to estimate the distribution is to simply look at a scatter plot of the samples.</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="181" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-pixel.png" alt="scatter_pixel" width="300" height="300" /></td>
<td width="316" valign="top">A scatter plot of a 2D sample set. (A pixel was simply drawn at each point of the sample. The images was slightly blurred to give the pixels more substance).Here we can already estimate the distribution, as we can intuitively &#8220;see&#8221; the shape.</td>
</tr>
<tr>
<td width="181" valign="top"></td>
<td width="316" valign="top"></td>
</tr>
</tbody>
</table>
<p>If the distribution is simple, we can often “guess” suitable parameters for a mathematical function. But this method is not suitable when more accuracy is required. And obviously this method does not work for higher dimensions.</p>
<p>I always use a visual inspection as a first step when using the other methods described here. First, it allows you to decide which approach to use. Second, it serves as a rough benchmark to test the results of a better method against.</p>
<h2>Averaging Over a Grid</h2>
<p>For this method, we divide the domain in cells, and count the number of points in each cell. To normalise, we divide the counts by the total number of points to get a distribution.</p>
<p>Typically, we choose a cell size large enough so that all cells contain a few points.</p>
<p>It is possible to use different cell sizes, so that regions of higher density has more cells, for instance, by using a quad tree. However, this approach makes it difficult to interpret the values (they should be scaled down by a factor of the area they represent), and to generate random numbers from this distribution. I can’t really imagine a situation where this approach will be preferred above using a regular grid or convolution.</p>
<h2>Convolution</h2>
<p>There are two ways to implement convolution. The first should be used when the sample set is small relative to the size of the domain, otherwise the second method will be more efficient.</p>
<h3>Sparse Point Convolution</h3>
<p>Generate a very granular empty grid over the domain.</p>
<p>For each point p in the sample set,</p>
<ul>
<li>map p to the grid (calculate the coordinates x,y of p in the grid),</li>
<li>add a number to all the cells in the neighbourhood of p in the grid.</li>
</ul>
<p>Now normalise the grid.</p>
<p>The neighbourhood is typically a circle or a square. The number you add can be the same for all neighbours (in which case any positive number will do), or it can be scaled depending on the distance from p.</p>
<p>The size of the neighbourhood depends on the density of your sample. In general, the denser it is, the smaller the neighbourhood can be. Smaller neighbourhoods lead to faster execution. To prevent “holes” in the approximation, use a radius that corresponds to the maximum of the distances between a point and its closest neighbour.</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="179" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-square16.png" alt="scatter_square16" width="300" height="301" /></td>
<td width="319" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/square.png" alt="square" width="100" height="100" />Estimation with a constant square neighbourhood.</td>
</tr>
<tr>
<td width="179" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-circle16.png" alt="scatter_circle16" width="300" height="300" /></td>
<td width="319" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/circle.png" alt="circle" width="100" height="100" /><br />
Estimation with a constant circular neighbourhood.</td>
</tr>
<tr>
<td width="179" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/scatter-cone16.png" alt="scatter_cone16" width="300" height="300" /></td>
<td width="319" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2009/03/cone.png" alt="cone" width="100" height="100" /><br />
Estimation with a circular neighbourhood with a falloff.</td>
</tr>
</tbody>
</table>
<h3>Traditional Convolution</h3>
<p>Generate a very granular empty grid over the domain.</p>
<p>For each point p in the sample set, map p to the grid (calculate the coordinates x,y of p in the grid), and add one to that location in the grid.</p>
<p>Now choose a square, symmetrical convolution matrix, and perform a discrete convolution on the grid:</p>
<p>new_grid[i, j] = sum_{i,j} grid[i][j] * c[i][j]</p>
<p>Here the i, j go over the indices of the convolution matrix. (Normally, the convolution is defined as new_grid[i, j] = sum_{i,j} grid[n - i][n - j] * c[i][j]. However, since we are suing a symmetrical matrix, these definitions are equivalent, and we need not perform the extra calculation).</p>
<p>Now normalise the grid.</p>
<p>The convolution can be a square or circle of 1s, or be filled with numbers that grow smaller outwards. These correspond to the three neighbourhoods described for the sparse convolution.</p>
<p>Note that the new_grid is larger than the original by one less than the size of the convolution matrix in each dimension. The centre of the new grid corresponds with the original grid.</p>
<p>For example, if the original grid was 100&#215;100, and the convolution matrix was 5&#215;5, the new grid will be 104&#215;104. The point (2, 2) in the new grid corresponds to point (0, 0) in the original grid.</p>
<h2>About Normalisation</h2>
<p>It is customary to normalise the distribution so that all the probabilities add to 1. But for many purposes we need only relative probabilities, and this step can be skipped. For example, the method of generating random numbers described in a previous post uses only relative probabilities.</p>
<h2>A Few Tips</h2>
<ul>
<li>Always test your distribution by <a href="http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/">generating a random set from it</a>, and comparing it with the original sample. They should match qualitatively.</li>
<li>The smaller your sample set, the cruder the approximation should be. That is, cells, neighbourhoods or convolution matrices should be big. There is a limit to the accuracy you can obtain from any sample – if you try to exceed it, your results will be poor.</li>
<li>The most common implementation errors are made at the borders (of any grid or matrix) – watch out for them!</li>
</ul>
<h2>Download</h2>
<p>There is an example of implementation in 2D in with the <a href="http://code-spot.co.za/python-image-code/">Python Image Code</a>. See the file random_distributions_demo.py.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F04%2F15%2Festimating-a-continuous-distribution-from-a-sample-set%2F&amp;linkname=Estimating%20a%20Continuous%20Distribution%20from%20a%20Sample%20Set"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/ynAnOtgbMjye4RPrK15Rm2dDClM/0/da"><img src="http://feedads.g.doubleclick.net/~a/ynAnOtgbMjye4RPrK15Rm2dDClM/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/ynAnOtgbMjye4RPrK15Rm2dDClM/1/da"><img src="http://feedads.g.doubleclick.net/~a/ynAnOtgbMjye4RPrK15Rm2dDClM/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/EakD68wdqEM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/04/15/estimating-a-continuous-distribution-from-a-sample-set/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=estimating-a-continuous-distribution-from-a-sample-set</feedburner:origLink></item>
		<item>
		<title>Generating Random Points from Arbitrary Distributions for 2D and Up</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/c2XTNJXuyzk/</link>
		<comments>http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 13:53:38 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[distribution function]]></category>
		<category><![CDATA[grids]]></category>
		<category><![CDATA[n-dimensional distributions]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[random distribution]]></category>
		<category><![CDATA[random number generation]]></category>
		<category><![CDATA[response curve]]></category>
		<category><![CDATA[Special Numbers Library]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=550</guid>
		<description><![CDATA[
I have already covered how to generate random numbers from arbitrary distributions in the one-dimensional case. Here we look at a generalisation of that method that works for higher dimensions.
The basic trick, while easy to understand, is hard to put in words (without reverting to mathematical equations). For two dimensions, we divide the plane into [...]]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline" title="header_rand_dist" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/header-rand-dist.png" alt="header_rand_dist" width="500" height="375" /></p>
<p>I have already covered <a href="http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/">how to generate random numbers from arbitrary distributions</a> in the one-dimensional case. Here we look at a generalisation of that method that works for higher dimensions.</p>
<p>The basic trick, while easy to understand, is hard to put in words (without reverting to mathematical equations). For two dimensions, we divide the plane into slices. Each slice is a 1D distribution. We also calculate a distribution from summing the frequencies in each slice. The latter distribution gives us one coordinate, and the appropriate slice to use. The distribution of that slice then gives the second coordinate. All distributions are put into inverse accumulative response curves as was done to generate <a href="http://code-spot.co.za/2008/09/21/generating-random-numbers-with-arbitrary-distributions/">one-dimensional random numbers</a>. (You should review that before implementing the 2D case).</p>
<p>In more dimensions, we also slice the space up into 1D distributions. Sums of these give us more distributions, which we can sum again, and again, until we reach a single distribution. This is used for the first coordinate, and to determine which distribution to use for the next coordinate. This goes on, until a 1D slice gives us the final coordinate. Again, all distributions are converted to inverse accumulative response curves.</p>
<p>If the above is unclear, I hope the detailed description below clears things up.</p>
<p><span id="more-550"></span></p>
<h2>Two Dimensions</h2>
<h3>Describe the Distribution</h3>
<p>Divide the domain into a regular grid. Let us use the domain 10..40 x 10..40. This means, all the points we will generate will fall in the square between the lines x = 10, x = 40, y = 10 and y = 40.</p>
<p>For later use, we will need the minimum x-coordinate of the domain (x0 = 10), the width of the domain (w = x1 – x0 = 40 – 10 = 30).</p>
<p>Assign to each cell the number of random numbers that should be generated for that cell for any suitable total of points. You need not normalise these values.</p>
<p>For our example we will use the 4&#215;4 grid shown below:</p>
<table border="0" cellspacing="0" cellpadding="0" width="500">
<tbody>
<tr>
<td width="125" valign="top">1</td>
<td width="125" valign="top">2</td>
<td width="125" valign="top">4</td>
<td width="125" valign="top">8</td>
</tr>
<tr>
<td width="125" valign="top">2</td>
<td width="125" valign="top">3</td>
<td width="125" valign="top">5</td>
<td width="125" valign="top">11</td>
</tr>
<tr>
<td width="125" valign="top">4</td>
<td width="125" valign="top">5</td>
<td width="125" valign="top">7</td>
<td width="125" valign="top">11</td>
</tr>
<tr>
<td width="125" valign="top">8</td>
<td width="125" valign="top">11</td>
<td width="125" valign="top">11</td>
<td width="125" valign="top">11</td>
</tr>
</tbody>
</table>
<p>For later use, we need the width of the grid (gw = 4).</p>
<p>The method described here won’t work if any of these values are 0.</p>
<h3>Calculate Cumulative Grids</h3>
<p>Calculate the cumulative sums for the columns of the array.</p>
<table border="0" cellspacing="0" cellpadding="0" width="500">
<tbody>
<tr>
<td width="125" valign="top">1</td>
<td width="125" valign="top">2</td>
<td width="125" valign="top">4</td>
<td width="125" valign="top">8</td>
</tr>
<tr>
<td width="125" valign="top">3</td>
<td width="125" valign="top">5</td>
<td width="125" valign="top">9</td>
<td width="125" valign="top">19</td>
</tr>
<tr>
<td width="125" valign="top">7</td>
<td width="125" valign="top">10</td>
<td width="125" valign="top">16</td>
<td width="125" valign="top">30</td>
</tr>
<tr>
<td width="125" valign="top">15</td>
<td width="125" valign="top">21</td>
<td width="125" valign="top">27</td>
<td width="125" valign="top">41</td>
</tr>
</tbody>
</table>
<p>Calculate a cumulative sum for the last row</p>
<table border="0" cellspacing="0" cellpadding="0" width="500">
<tbody>
<tr>
<td width="125" valign="top">15</td>
<td width="125" valign="top">36</td>
<td width="125" valign="top">63</td>
<td width="125" valign="top">104</td>
</tr>
</tbody>
</table>
<h3>Construct Inverse Response Curves</h3>
<p>For each column of cumulative sums, append a zero at the beginning, and create an inverse response curve as described for the one dimensional case. Thus the first columns inverse response curve will be created from 0, 1, 3, 7, 15. Call these curves cy[0] … cy[3].</p>
<p>For the row of cumulative sums, append a zero at the beginning, and create an inverse response curve. Call this curve cx.</p>
<h3>Determine Random Point</h3>
<p>You are now ready to generate random points from the specified distribution.</p>
<p>First, generate two uniform random numbers, urx and ury.</p>
<p>Use urx to do a lookup into curve c[x]. The result rx gives the x-coordinate of your non-uniform random number. Use this number to decide which column curve to use: subtract the minimum domain x-coordinate, divide it by the domains width, multiply it by the number of columns, and floor it to an integer.</p>
<p>ix = (rx – x0)/w * gw</p>
<p>Now use ury to do a lookup in cy[ix]. The result ry is the y-coordinate of the number.</p>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="rand_dist_red" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/rand-dist-red.png" alt="rand_dist_red" width="200" height="200" align="left" />This image shows a plot of samples generated from the distribution specified above (normalised to fit in the image boundaries). Brighter areas indicate that more points occur in that region.</p>
<p>Visually, it looks like the sample mimics the original distribution well.</p>
<h2>N Dimensions</h2>
<h3>Describe the Distribution</h3>
<p>Divide the domain in a regular N-dimensional grid, and assign frequencies to cells in the grid. For future calculations, we will need the lowest coordinate of the domain along each dimension (x0_k), the width of the domain for each dimension (w_k), and the number of cells in the grid for each dimension (gw_k).</p>
<h3>Calculate Cumulative Grids</h3>
<p>Accumulate sums along one dimension in a N-dimensional grid G_N. The last subgrid contains the totals of all “columns” along that dimension, and is a (N-1) dimensional structure.</p>
<p>Accumulate sums of this subgrid into a (N-1) dimensional grid G_(N-1) along another dimension. Again, the last subgrid contains the totals of the columns of that dimension.</p>
<p>This must be repeated until a single row, G_1 is produced. In general, the last subgrid in G_k contains the totals of columns in G_(k-1) along dimension k. This must be accumulated in a (k-1)-dimensional grid G_(k-1).</p>
<h3>Construct Inverse Response Curves</h3>
<p>Now for each grid G_k, we need to construct inverse response curves from the columns along dimension k. Remember to append 0 at the beginning of each column. The curves must be put into a k-1-dimensional structure, C_k.</p>
<h3>Determine Random Point</h3>
<p>Generate N uniformly distributed random numbers ur_1…ur_N.</p>
<p>Use ur_1 to do a lookup in C_1. The result r_1 is the first coordinate of your point. Use it to determine to calculate an appropriate index i_1:</p>
<p><span style="font-family: 'Courier New'; line-height: 18px; white-space: pre;">i</span>_1 = (ur_1 – x0_1)/w_1 * gw_1</p>
<p>i_1 is the index of the curve to use from C_2: lookup ur_2 in C_2[i_1] to obtain r_2. This is the second coordinate of your point. Determine i_2:</p>
<p><span style="font-family: 'Courier New'; line-height: 18px; white-space: pre;">i</span>_2 = (ur_2 – x0_2)/w_2 * gw_2</p>
<p>i_1 and i_2 determine the curve to use from C3, i.e. the curve C3[i_1, i_2].</p>
<p>Repeat this process until all coordinates are determined. In general, use ur_k to do a lookup in C_k[i_1, i_2, …, i_(k-1)] to obtain r_k. Use this to calculate i_k:</p>
<p><span style="font-family: 'Courier New'; line-height: 18px; white-space: pre;">i</span>_k = (ur_k – x0_k)/w_k * gw_k</p>
<p>That’s it!</p>
<h2>Download</h2>
<p>There is an example of implementation in 2D in with the <a href="http://code-spot.co.za/python-image-code/">Python Image Code</a>. See the file random_distributions_demo.py. (I know it is annoying that it is coupled with all the other image code… I am working on a better solution!)</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F04%2F15%2Fgenerating-random-points-from-arbitrary-distributions-for-2d-and-up%2F&amp;linkname=Generating%20Random%20Points%20from%20Arbitrary%20Distributions%20for%202D%20and%20Up"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/Z62zq7iTB0MDnfZYDFD9w43Snpo/0/da"><img src="http://feedads.g.doubleclick.net/~a/Z62zq7iTB0MDnfZYDFD9w43Snpo/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/Z62zq7iTB0MDnfZYDFD9w43Snpo/1/da"><img src="http://feedads.g.doubleclick.net/~a/Z62zq7iTB0MDnfZYDFD9w43Snpo/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/c2XTNJXuyzk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/04/15/generating-random-points-from-arbitrary-distributions-for-2d-and-up/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=generating-random-points-from-arbitrary-distributions-for-2d-and-up</feedburner:origLink></item>
		<item>
		<title>Cellular Automata for Simulation in Games</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/c_NirXyj_Kk/</link>
		<comments>http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 08:34:57 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Simulation]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[blending]]></category>
		<category><![CDATA[cellular automata]]></category>
		<category><![CDATA[Conway's game of life]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[diffusion]]></category>
		<category><![CDATA[discrete dynamics]]></category>
		<category><![CDATA[disease simulation]]></category>
		<category><![CDATA[fire simulation]]></category>
		<category><![CDATA[Game Maker]]></category>
		<category><![CDATA[grids]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[probability]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[sampling]]></category>
		<category><![CDATA[social dynamics]]></category>
		<category><![CDATA[tiles]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=499</guid>
		<description><![CDATA[
A cellular automata system is one of the best demonstrations of emergence. If you do not know what cellular automata (CA) is, then you should go download Conway&#8217;s Game of Life immediately:
Conway’s Game of Life
Essentially, CA is a collection of state machines, updated in discrete time intervals. The next state of one of these depends [...]]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline" title="header" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/header1.png" alt="header" width="500" height="371" /></p>
<p>A cellular automata system is one of the best demonstrations of emergence. If you do not know what cellular automata (CA) is, then you should go download Conway&#8217;s Game of Life immediately:</p>
<p><a href="http://psoup.math.wisc.edu/Life32.html">Conway’s Game of Life</a></p>
<p>Essentially, CA is a collection of state machines, updated in discrete time intervals. The next state of one of these depends on the current state as well as the states of neighbours. Usually, the state machines correspond to cells in a grid, and the neighbours of a cell are the cells connected to that cell. For a more detailed explanation, see <a href="http://en.wikipedia.org/wiki/Cellular_automata">the Wikipedia article</a>.</p>
<p>Even simple update rules can lead to interesting behaviour: patterns that cannot be predicted from the rules except by running them. With suitable rules, CA can simulate many systems:</p>
<ul>
<li>Natural phenomena: weather, fire, plant growth, migration patterns, spread of disease.</li>
<li>Socio-economic phenomena: urbanisation, segregation, construction and property development, traffic, spread of news.</li>
</ul>
<p><span id="more-499"></span></p>
<p>In games, these can be used as game elements (such as fire and disease), or they can also add some decorative life to a game (such as city development in a simulation game).</p>
<p>The great thing about CA systems is that they are not hard to implement, and they have intrinsic fun value (I mean here, for the programmer!).</p>
<p>Before we get into the details, let me add a small disclaimer here:</p>
<ul>
<li>This tutorial is not comprehensive. I only touch on a few ideas in a wide field. See some of the resources at the end for more information.</li>
<li>This tutorial is not representative. I merely chose topics I found interesting or thought would be useful for game developers.</li>
<li>I am not suggesting that using cellular automata is the best way to simulate any of the examples given here. For any problem, there might be solutions that are faster, easier to implement, or yield better results.</li>
</ul>
<h2>Implementation</h2>
<p>To implement a CA system, you need to do the following:</p>
<ul>
<li>Use a suitable system to store states, for example, a 2D array.</li>
<li>Decide on a suitable neighbourhood shape, and work out some preliminary rules. Decide how you will handle edges.</li>
<li>Implement a suitable way to describe your rules.</li>
<li>Implement an update function that hooks into the main game loop.</li>
<li>Implement a visualisation scheme (for example, drawing tiles depending on states in the array).</li>
</ul>
<p>Some details of these are described below.</p>
<h3>Grid</h3>
<p>A typical implementation uses two grids for storing states. One is the current world state; the other is the new world state. Once all cells have been updated for the current iteration, pointers to the arrays can be swapped. This way updating the cells one by one will not have an effect on other cells until the next iteration, and you do not have to create a new array in each iteration.</p>
<p>Using grids with square cells are the easiest to implement, but the concept is also applicable to other grids: hexagonal and triangular grids are also common, and even polar grids have been used to simulate spiral star systems.</p>
<p>It is also possible to use irregular systems, although the implementation then becomes a challenge. One example of an irregular system is a presentation based on a Poisson distribution of points. The trick here is to find an efficient way to locate neighbours. Fortunately, this problem has already been solved in creating the points (see the <a href="http://devmag.org.za/articles/55-POISSON-DISK-SAMPLING/">Poisson Sampling tutorial in Dev.Mag</a> and download code from <a href="http://www.luma.co.za/labs/tag/poisson-disk/">Luma Labs</a>). It is in fact done by using an invisible grid! Of course, visualising a state is also a bit more difficult.</p>
<h3>Neighbourhoods</h3>
<p>For 2D cellular automata, the most common neighbourhoods are the Von Neumann neighbourhood and the Moore neighbourhood, shown below (the blue cell’s neighbourhood is shown in red). Other neighbourhoods are also possible.</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="166" valign="top"><img style="display: inline" title="vonneumann" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/vonneumann.png" alt="vonneumann" width="88" height="88" /></td>
<td width="166" valign="top"><img style="display: inline" title="moore" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/moore.png" alt="moore" width="88" height="88" /></td>
<td width="166" valign="top"><img style="display: inline" title="road" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/road.png" alt="road" width="88" height="88" /></td>
</tr>
<tr>
<td width="166" valign="top">Von Neumann neighbourhood</td>
<td width="166" valign="top">Moore neighbourhood</td>
<td width="166" valign="top">Extended Von Neumann neighbourhood</td>
</tr>
</tbody>
</table>
<p>The cell can be included in the neighbourhood or not. It is advisable to keep the neighbourhoods as small as possible: not only does the neighbourhood size impact performance, it also affects the number of rules to be specified and thus the tweaking complexity.</p>
<h3>Specifying Update Rules</h3>
<p>Specifying the rules concisely is the most challenging part of implementing CA. With very simple models, you might want to use a few if/else statements. This, however, makes it hard to modify (tweak or extend), and is therefore not suitable for more complicated systems.</p>
<p>It is best to implement rules as a table that can be indexed using the neighbourhood states.</p>
<p><strong>Table as an array.</strong> In this method, each row represents the combined state of the surrounding cells. The final entry in the row is the new state of the current cell. Each of the remaining columns represents a state. The entries in these columns represent the number of cells surrounding the current cell in that state.</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="125" valign="top">Dry Bush</td>
<td width="125" valign="top">Burning Bush</td>
<td width="125" valign="top">Charcoal</td>
<td width="125" valign="top">New State</td>
</tr>
<tr>
<td width="125" valign="top">4</td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">Dry Bush</td>
</tr>
<tr>
<td width="125" valign="top">3</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">Burning Bush</td>
</tr>
<tr>
<td width="125" valign="top">3</td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">Dry Bush</td>
</tr>
<tr>
<td width="125" valign="top">2</td>
<td width="125" valign="top">2</td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">Burning Bush</td>
</tr>
<tr>
<td width="125" valign="top">2</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">1</td>
<td width="125" valign="top">Burning Bush</td>
</tr>
<tr>
<td width="125" valign="top">2</td>
<td width="125" valign="top">0</td>
<td width="125" valign="top">2</td>
<td width="125" valign="top">Burning Bush</td>
</tr>
</tbody>
</table>
<p>A cell surrounded with three cells in the Dry Bush state and one cell in the Burning Bush state will go into the Burning Bush state.</p>
<p>This table can be quite large, so that you must take care to implement lookups efficiently. Keep the table sorted, and perform binary search to lookup entries. Below are some improvements on this scheme.</p>
<p><strong>Table as a tree.</strong> In the table above, it is easy to see that if there are three dry bush nodes, there are two possibilities for the other states (either 1 0, or 0 1). We can use this to implement a tree. Each level in the tree represents a state. A value in a node represents how many cells in the neighbourhood are in that state. A path from root to leaf fully describes the states of the entire neighbourhood. We do not add nodes for the last state, as it is uniquely determined by the other states.</p>
<p>Below is a tree corresponding to the piece of table above.</p>
<p>BB = Burning Bush</p>
<p>DB = Dry Bush</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="41" valign="top">root</td>
<td width="45" valign="top">+&#8212;</td>
<td width="50" valign="top">DB 4</td>
<td width="50" valign="top"></td>
<td width="49" valign="top"></td>
<td width="171" valign="top">DB</td>
</tr>
<tr>
<td width="42" valign="top"></td>
<td width="45" valign="top">+&#8212;</td>
<td width="50" valign="top">DB 3</td>
<td width="50" valign="top">+&#8212;</td>
<td width="49" valign="top">BB 1</td>
<td width="171" valign="top">BB</td>
</tr>
<tr>
<td width="41" valign="top"></td>
<td width="45" valign="top">|</td>
<td width="50" valign="top"></td>
<td width="50" valign="top">+&#8212;</td>
<td width="49" valign="top">BB 0</td>
<td width="171" valign="top">DB</td>
</tr>
<tr>
<td width="41" valign="top"></td>
<td width="45" valign="top">+&#8212;</td>
<td width="50" valign="top">DB 2</td>
<td width="50" valign="top">+&#8212;</td>
<td width="49" valign="top">BB 2</td>
<td width="171" valign="top">BB</td>
</tr>
<tr>
<td width="41" valign="top"></td>
<td width="45" valign="top"></td>
<td width="50" valign="top"></td>
<td width="50" valign="top">+&#8212;</td>
<td width="49" valign="top">BB 1</td>
<td width="171" valign="top">BB</td>
</tr>
<tr>
<td width="41" valign="top"></td>
<td width="45" valign="top"></td>
<td width="50" valign="top"></td>
<td width="50" valign="top">+&#8212;</td>
<td width="49" valign="top">BB 0</td>
<td width="171" valign="top">BB</td>
</tr>
</tbody>
</table>
<p>This is a more efficient implementation; unfortunately, it is also more complicated. It is inconvenient to specify the tree in a tree-friendly format (XML or s-expressions, for example). You still need to specify it in table format (space separated text file, for example) and build the tree from that.</p>
<p><strong>Implementation as a hash table.</strong> Here you use tuples of state counts as keys. For example, the third entry in the table above can be accessed with the tuple (3, 0, 1). If your implementation language does not support tuples, you might need to implement them yourself. Be sure to make them immutable!</p>
<p><strong>Implementation as an N-dimensional array.</strong> This is a very simple method, although it wastes a lot of memory. N is the number of states, and we use the state counts to index into the array. In our example, we will use a 3D array, so that the third element can be accessed using transition_array[3, 0, 1].</p>
<p>The method above can be used even when the implementation language does not provide N dimensional arrays. Simply use a 1D array, and interpret the state counts as the digits of a base-4 number. Thus, the third row will be located at 3*16 + 0*4 + 1*1 = 49.</p>
<p>Note that since the numbers are restricted by the requirement that they add to four, there will be unused array positions in both these last two methods. You can save memory by not using the last state to index (since it is uniquely determined by the other states). Thus, we can use a 2D array, and access the 3,0,1 rule with 3,0 alone: transition_array[3, 0]. Alternatively, if we need to use a 1D array, we can store the rule in the position 3*4 + 0*1 = 12. Although the same scheme is possible for the hash table implementation, I would advise you to use the full indexing scheme instead, since it will not waste more memory if you do, and it is somewhat easier to understand if you use full indices.</p>
<p>Some rules do not need the detailed tables above. For instance, in a system of only two states, where transitions depend on the count of the states of the neighbourhood, we can use a simple array, indexed by one of the states’ counts. Many other schemes are possible: in general, aim for quick lookups and easy specification.</p>
<h3>Edges</h3>
<p>The edges of your simulation might present some problems: edges often serve as unwanted sources, sinks or stabilisers.</p>
<p>A <strong>source</strong> is the origin of outward growth (states change progressively to a specific state in an outward direction).</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="125" valign="top"><img style="display: inline" title="growth4" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth41.png" alt="growth4" width="88" height="88" /></td>
<td width="125" valign="top"><img style="display: inline" title="growth3" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth31.png" alt="growth3" width="88" height="88" /></td>
<td width="125" valign="top"><img style="display: inline" title="growth2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth21.png" alt="growth2" width="88" height="88" /></td>
<td width="125" valign="top"><img style="display: inline" title="growth1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth11.png" alt="growth1" width="88" height="88" /></td>
</tr>
</tbody>
</table>
<p>A <strong>sink</strong> is the exact opposite:</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="125" valign="top"><img style="display: inline" title="growth1" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth11.png" alt="growth1" width="88" height="88" /></td>
<td width="125" valign="top"><img style="display: inline" title="growth2" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth21.png" alt="growth2" width="88" height="88" /></td>
<td width="125" valign="top"><img style="display: inline" title="growth3" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth31.png" alt="growth3" width="88" height="88" /></td>
<td width="125" valign="top"><img style="display: inline" title="growth4" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/growth41.png" alt="growth4" width="88" height="88" /></td>
</tr>
</tbody>
</table>
<p>Sources and sinks are emergent properties of the CA system, and are not physical attributes of the cells.</p>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="screenshot186" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1861.png" alt="screenshot186" width="144" height="108" align="left" /> A <strong>stabiliser</strong> is a section that keeps neighbouring states fixed. For example, in the fire simulation (described below), there is an unnatural wall of fire around the edges at the end of the simulation.</p>
<p>There are several ways you can handle edges:</p>
<p><strong>Ignore them.</strong> When the edge anomalies are acceptable, it is best not to complicate the model. This is only possible if the rules are specified in a way that does not require state counts to sum to the size of the neighbourhood. For example, if there is a rule “if num_states_fire &gt; 1, then …”.</p>
<p><strong>Wrap around.</strong> This solution is very elegant, easy to implement, and its effects are easy to understand. However, it is usually easy to see that the world has been wrapped in this way, and hence it is not always a visually a satisfactory solution. It is possible, however, to simulate a grid bigger than displayed area (say about double). This will hide the fact that it is wrapped, but still give you the benefits of having a world without any discontinuities.</p>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="wrapped" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/wrapped.png" alt="wrapped" width="88" height="88" align="left" /> In the CA system shown left, we want to calculate the next state of the grey cell. Two neighbours fall outside the edges. If we wrap around, we use the four red squares as shown.</p>
<p><strong>Reflection.</strong> Use a neighbouring state to perform calculations.</p>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="reflect" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/reflect.png" alt="reflect" width="88" height="88" align="left" /> The CA system shown left is the same situation as above. If we use neighbouring states for the cells beyond the edges, we use the state of the grey cell (twice!), in addition to the two red cells shown.</p>
<p><strong>Fix their states. </strong>The edges can be given special, constant states that make the CA behave as intended. Finding the right state(s) for the edges might be difficult.</p>
<p>An implementation trick that applies to the last three edge-handling techniques is to include a border in your simulation. For the Von Neumann and Moore neighbourhoods, this border is only one cell thick.</p>
<p>This border is used for updates like all other cells, but is itself updated differently. The update rules for wrapping and reflection will simply copy states from the right places; the border for fixed states will never be updated.</p>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="edges_implementation" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/edges-implementation.png" alt="edges_implementation" width="123" height="123" align="left" /> In the figure, hatched cells are updated according to the special rules of the edge-handling scheme – in this case, wrapping is used, so they are simply copied from the appropriate cells. All other cells are updated normally. Note that here we do not need special logic for updating the grey cell.</p>
<h2>A Few Examples</h2>
<p>(Also see the downloads at the bottom of the post).</p>
<h3>Heat</h3>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="screenshot210" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot210.png" alt="screenshot210" width="144" height="108" align="left" /> Here, continuous states (floats between 0 and 1) are used. Every cell is updated to a weighted average of its Moore neighbourhood cells: corners have a smaller weight than other cells. For this simulation, heat sinks and sources have been added: they keep the cell’s temperature at 0 and 1 respectively.</p>
<h3>City Roads</h3>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="roads" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/roads.png" alt="roads" width="144" height="108" align="left" /> This simulation use separate neighbourhoods for creating and destroying a road. The creation neighbourhood is an extended Von Neumann neighbourhood; the destruction neighbourhood is a Moor neighbourhood. Creation and destruction is according to probabilities based on the count of neighbouring roads.</p>
<h3>Influence</h3>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="anger" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/anger.png" alt="anger" width="288" height="216" align="left" /></p>
<p>This simulation models human emotion as influenced by others. A character has an internal state, and an externally visible state. Characters can only observer the external state of their neighbours. The internal state is then a modified: a character surrounded by angry people will itself become angry, and so on. The external state is probabilistically determined by the internal state.</p>
<h3>Disease Spread</h3>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="epeidemic" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/epeidemic.png" alt="epeidemic" width="288" height="216" align="left" /> For our game <a href="http://www.luma.co.za/labs/2007/10/15/epidemic/">Epidemic</a>, <a href="http://blog.cunnington.co.za/">Chris</a> and I used a simple diffusion model. We used a floating-point number for the state, and represented the number of infected people in a cell. We used different colours for different ratios to visualise infection. At each time step, a cell would become infected by an amount proportional to that of the neighbourhood, with some random scaling.</p>
<h2>Visualising States</h2>
<h3>Versions of tiles</h3>
<p>A very effective way of making CA simulations more impressive is to have more than one tile for each state, and display them randomly. This is especially helpful for hiding regularity in off-line simulations. Tile sets with different versions for corners, edges, and central regions can drastically improve the look of the game, although it complicates choosing the correct tile version. In addition, it means you need tiles for various combinations of states. Assuming we can rotate and reflect tiles, in the fire example with three states, we need the following tiles:</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="250" valign="top">3 centre tiles</td>
<td width="59" valign="top"><img style="display: inline" title="centre" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/centre1.png" alt="centre" width="49" height="49" /></td>
</tr>
<tr>
<td width="250" valign="top">3 straight-edge tiles</td>
<td width="59" valign="top"><img style="display: inline" title="edge" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/edge1.png" alt="edge" width="49" height="49" /></td>
</tr>
<tr>
<td width="250" valign="top">3 diagonal line tiles</td>
<td width="59" valign="top"><img style="display: inline" title="diagonal" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/diagonal1.png" alt="diagonal" width="49" height="49" /></td>
</tr>
<tr>
<td width="250" valign="top">3 cross tiles</td>
<td width="59" valign="top"><img style="display: inline" title="cross" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/cross1.png" alt="cross" width="49" height="49" /></td>
</tr>
<tr>
<td width="250" valign="top">6 corner tiles</td>
<td width="59" valign="top"><img style="display: inline" title="corner" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/corner1.png" alt="corner" width="49" height="49" /></td>
</tr>
<tr>
<td width="250" valign="top">3 half-straight tiles</td>
<td width="59" valign="top"><img style="display: inline" title="half_edge" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/half-edge1.png" alt="half_edge" width="49" height="49" /></td>
</tr>
</tbody>
</table>
<p>This is 21 tiles for only three states. It is advisable to automate tile creation.</p>
<h3>Tile <a name="_Toc226913823"></a></h3>
<p>States can be animated. Instead of displaying a single tile, display an animation sequence. You will need to think about how to start and stop these animations so that they are seamless. For instance, you can make all animation sequences the same length, and only update states between animation sequences.</p>
<p>You can also increase the seamlessness of the simulation by animating transitions between states. This can be as easy as blending between two tiles over a period of time (assuming that updates are made far enough apart).</p>
<h3>No Tiles</h3>
<p>Instead of using tiles to represent a state of a cell, you can put objects in a cell. For instance, in a plant growth simulation, you can put a number of trees in the cell depending on the state. The advantages of this are:</p>
<ul>
<li>You do not have to create dozens of tiles for variety.</li>
<li>The player can interact with the objects. For instance, the plant placement of trees can hinder a player’s movement.</li>
</ul>
<p><img style="display: inline; margin: 5px 10px 0px 0px" title="detail" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/detail1.png" alt="detail" width="140" height="108" align="left" /> This shows a simple forest simulation. Trees grow and die depending on the surrounding trees. This system uses a grid, but not tiles: trees can grow in random positions in tiles. For this simulation, three random coordinates have been chosen for each cell at the beginning of the simulation. Depending on the states, one, two, or three trees will be drawn at these points. Choosing a fixed set of points makes it easier to draw trees at the same coordinates every tick. A somewhat more complicated simulation can choose new points whenever a new tree comes into being.</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="166" valign="top"><img style="display: inline" title="screenshot191" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1911.png" alt="screenshot191" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot193" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1931.png" alt="screenshot193" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot196" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1961.png" alt="screenshot196" width="144" height="108" /></td>
</tr>
</tbody>
</table>
<h2>CA Enhancements</h2>
<p>The images below show three frames from a simple fire simulation.</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="166" valign="top"><img style="display: inline" title="screenshot181" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1811.png" alt="screenshot181" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot182" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1821.png" alt="screenshot182" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot183" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1831.png" alt="screenshot183" width="144" height="108" /></td>
</tr>
</tbody>
</table>
<p>The green is grass (Dry Bush), the orange is fire (Burning Bush) and the brown is burnt grass (Charcoal).</p>
<p>As you can see, the simulation captures some features of a fire:</p>
<ul>
<li>fire grows outward,</li>
<li>grass only burns once,</li>
<li>grass needs fire to catch fire (there is no spontaneous combustion).</li>
</ul>
<p>Even so, the symmetry and regularity makes this fire very unconvincing. Below we look at some ideas to enhance a simple CA simulation.</p>
<h3>Probabilistic State Transitions</h3>
<p>Instead changing to some specific state based on the surrounding states, you can change to any state with some probability. These probabilities depend on the surrounding states, and can possibly be zero.</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="166" valign="top"><img style="display: inline" title="screenshot167" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1671.png" alt="screenshot167" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot168" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1681.png" alt="screenshot168" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot169" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1692.png" alt="screenshot169" width="144" height="108" /></td>
</tr>
<tr>
<td width="166" valign="top"><img style="display: inline" title="screenshot170" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1702.png" alt="screenshot170" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot171" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1712.png" alt="screenshot171" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot172" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1721.png" alt="screenshot172" width="144" height="108" /></td>
</tr>
<tr>
<td width="166" valign="top"><img style="display: inline" title="screenshot173" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1731.png" alt="screenshot173" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot174" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1741.png" alt="screenshot174" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot175" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1751.png" alt="screenshot175" width="144" height="108" /></td>
</tr>
</tbody>
</table>
<p>Adding probability to the mix can have several advantages:</p>
<p><strong>It introduces variability in patterns.</strong> This means a specific (perhaps the start-up pattern) will not always produce the same results.</p>
<p><strong>It can enhance the organic look of the system.</strong> Cross and squares patterns are common in deterministic CA systems. For many purposes, this is unsatisfactory (have you ever seen a fire spreading as a growing square?) Adding probabilistic state changes will make the patterns more organic and varied.</p>
<p><strong>It can make discreet behaviour more continuous.</strong> For example, two common &#8220;problems&#8221; with CA systems are exponential growth (where all cells go to a certain state outwards very quickly), or sudden death (where all cells go to a certain state very quickly inwards). The problem is often that a single change in the update rules results in a exponential growth system to become a sudden death system, with seemingly no way to get a &#8220;sweet spot&#8221;. If states can only change with a certain probability, tweaking the probabilities allows you to get intermediate patterns (stable growth, equilibrium, or stable death).</p>
<p><strong>It allows you to control the speed of the simulation.</strong> It is especially helpful to slow down a simulation without making it more granular (in the time dimension). It is useful to multiply all your probabilities with a global parameter that you can tweak to control the speed.</p>
<p>Note that in the example above, certain cells did not burn at all – per chance, they did not caught fire when their neighbours were burning. Timers (see below) can reduce or eliminate this effect.</p>
<p>Adding randomness can increase the emergence, and hence also unwanted emergence, so care must be taken that the simulation is always valid.</p>
<h3>Tile Interpolation</h3>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="166" valign="top"><img style="display: inline" title="screenshot169" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1693.png" alt="screenshot169" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot170" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1703.png" alt="screenshot170" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot171" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1713.png" alt="screenshot171" width="144" height="108" /></td>
</tr>
</tbody>
</table>
<p>Normally, you want your simulation to be as simple as possible. However, when such simple simulations are displayed (visualised), the results can be unsatisfactory. One way to get better visual quality is to use tile (cell) interpolation to make the simulation seem more complicated than it really is. When combined with a bit of randomisation, the effects can be very convincing.</p>
<p>The basic idea is to simulate only every nth cell with the CA approach. Other cells are interpolated. The number of interpolated cells can be adjusted, depending on the detail level required (balanced with the combinatorial number of tiles required!)</p>
<p>In the fire simulation, using only three states makes the simulation seem very primitive. Suppose that we simulate only every second row, and in these, only every second column, and fill the remaining cells depending on their neighbours. We have to create a function that will return a tile for each combination of surrounding tiles:</p>
<p>get_center_tile(north, east, south, west)</p>
<p>Interpolation rules are similar to update rules of the simulation, and hence can easily be as complicated. If this is the case, you would do better to implement more states and not do any interpolation. Interpolation should only be used if it significantly reduces the implementation complexity.</p>
<h3>Timers</p>
<table border="0" cellspacing="0" cellpadding="0">
<tbody></tbody>
</table>
</h3>
<table border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="166" valign="top"><img style="display: inline" title="screenshot177" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1771.png" alt="screenshot177" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot178" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1781.png" alt="screenshot178" width="144" height="108" /></td>
<td width="166" valign="top"><img style="display: inline" title="screenshot179" src="http://code-spot.co.za/blog/wp-content/uploads/2009/04/screenshot1791.png" alt="screenshot179" width="144" height="108" /></td>
</tr>
</tbody>
</table>
<p>Some interesting effects can be obtained if each cell has a timer, that is, each cell only updates once the timer expires. Some rule determines when the timer is reset. For instance, the timer can be set:</p>
<ul>
<li>randomly,</li>
<li>as a function of the state,</li>
<li>as a function of the surrounding cells,</li>
<li>as a function of another property of the tile (*1),</li>
<li>as a function of some external process (*2).</li>
</ul>
<p>(*1) For instance, if each cell has an associated &#8220;burning capacity&#8221; parameter, (simulating material types), a fire state timer can be set in proportion to this parameter.</p>
<p>(*2) For example, we can set timers according to a wind factor.</p>
<p>Timers can have the following effects:</p>
<ul>
<li>add some randomness to a simulation,</li>
<li>slow the simulation down,</li>
<li>smear the simulation (for example, in the fire simulation, the burning border is much thicker, and no cells are skipped).</li>
</ul>
<p>Although you can often implement your grid cells as classes (or structs, or whatever aggregating construct your language provides) with states and timers embedded, it is simpler (on more efficient) to have separate integer grids – one for states and one for timers.</p>
<p>Note that if timers do not have the same expiration time, you the CA system is asynchronous and the behaviour can differ dramatically from a synchronous CA system. Thus, you should include timers early in the development process, so that their effect does not force you to re-tweak all the parameters.</p>
<h2><a name="_Toc226913828"></a></h2>
<p>If your world is big, you cannot run the CA for the whole world at every time step – it will kill performance. Below are some ideas for improving performance.</p>
<h3><a name="_Toc226913829"></a></h3>
<p>Instead of simulating the entire world, you can only simulate the part that is relevant to the game, usually the visible region of the game. A simple technique is to use a wrapped grid, similar to the grids used for the visual port in scrollable 2D games. This grid can be slightly larger than the visible grid, so that it allows cells to update naturally for a few iterations before they become visible, and so increase the illusion of a persistent world.</p>
<p>To hide that fact that you are only simulating a very small piece of the world, you must update “new” cells appropriately. There are several options:</p>
<p><strong>Update cells to a natural starting state.</strong> In many cases, this solution is adequate, especially if you simulate a slightly larger grid than is visible.</p>
<p><strong>Copy states from the existing simulation.</strong> Here you can copy neighbouring cells, or randomly from a nearby region. Copying from nearby cells promotes spatial coherence.</p>
<p><strong>Initialise states statistically.</strong> Based on a neighbourhood of cells, each cell is initialised probabilistically. For example, each cell can be initialised randomly to one of three neighbouring cell’s states.</p>
<p><strong>Use hierarchical modelling.</strong> Use another CA system that represents the entire world in very low detail, and use this to initialise the cells of the high detail version. Note that both the states and the update rules will differ for the high and low detail simulations. Use probabilities to prevent homogeneous systems. You can even use several levels of detail, and incorporate them as needed. Beware the extra implementation complexity, though!</p>
<p>This technique does not work when the world is should be changed permanently.</p>
<h3><a name="_Toc226913830"></a></h3>
<p>Instead of only simulating a part of the world, you can only update a part of the world. This requires enough memory for the whole world, but only processing power for the cells you wish to update. This method has the advantage of real persistence, thus permanent changes can be reliably simulated. Which cells you update will determine how your simulation will play out:</p>
<ul>
<li>Update all visible cells (or a slightly larger region). This is the most natural update scheme, and its effects are similar to partial simulation described above.</li>
<li>Divide the world into discontiguous regions, and update a different region each time step. For example, divide the world into two sets: one contains every other cell, the other the rest, and update these two sets alternately. To save a significant amount of processing, you need many sets. To hide patterns in the updates that might break the illusion of a continuous world, the sets should be irregular. This method has the advantage that real things happen off screen. On the down side, it slows down the simulation significantly.</li>
<li>Combine the two methods above.</li>
</ul>
<p>Partial updating, like the inclusion of timers, lead to an asynchronous system, and hence the behaviour might be very different from that of a fully updated system.</p>
<h3><a name="_Toc226913831"></a></h3>
<p>In certain cases, simulations can be baked offline and be used in games. This means you perform the simulation before the time, and record each frame. The game then reads these frames, and plays them back.</p>
<p>Various schemes are possible to get more with less. For instance, you can also interpolate the simulation in time. With some thought, you can simulate events in a way that they can be looped, stacked together, and started and stopped unobtrusively. This means you can blend them with the interaction in a way that will not make it obvious that the simulation has been performed off-line.</p>
<h3>Unwanted Emergence</h3>
<p>Not all emergence is good, and you might find it hard to prevent certain behaviours. If the unwanted behaviour is only visual, and it occurs only rarely, it might be acceptable. However, if behaviour impacts play negatively, it must be prevented.</p>
<p>As with all tweaking, you should not spend too much time fumbling around. To proceed more &#8220;scientifically&#8221;, ask yourself the following questions:</p>
<ul>
<li>Is there a way to detect (measure objectively) the unwanted behaviour?</li>
<li>Instead of tweaking your CA, can you detect-and-recover system be used?</li>
<li>Is the behaviour continuous? In other words, is there a degree of badness, or is it either good or bad?</li>
<li>If it is continuous, is it feasible to kick in a preventative system? (When the badness goes above a threshold, updates are processed differently).</li>
<li>Is it feasible to find a set of parameters through an optimisation algorithm (for instance, genetic programming)? It might even be possible to search exhaustively for a solution.</li>
<li>Is my model too complex? Try to eliminate states and simplify transition rules. You might even consider breaking your simulation into two or more independent CA systems.</li>
<li>If you find yourself struggling to tweak the parameters for too long, you should perhaps look for a better model that is less sensitive to the exact parameters.</li>
</ul>
<h2>Links</h2>
<h3>General</h3>
<p><a href="http://cell-auto.com/">http://cell-auto.com/</a> A nice breakdown of various topics related to Cellular Automata. The article on <a href="http://cell-auto.com/optimisation/">optimisation</a> is especially interesting.</p>
<p><a href="http://www.collidoscope.com/modernca/">http://www.collidoscope.com/modernca/</a> Contains many non-traditional variations of cellular automata.</p>
<p><a href="http://www.fourmilab.ch/cellab/">http://www.fourmilab.ch/cellab/</a> Application for exploring cellular automata.</p>
<h3>Applications and Implementation</h3>
<p><a href="http://realtimecollisiondetection.net/blog/?p=57">http://realtimecollisiondetection.net/blog/?p=57</a> Path finding using cellular automata.</p>
<p><a href="http://www.ibm.com/developerworks/java/library/j-camusic/">http://www.ibm.com/developerworks/java/library/j-camusic/</a> Cellular Automata and music (interesting way of creating procedural music).</p>
<p><a href="http://blog.sigfpe.com/2006/12/evaluating-cellular-automata-is.html">http://blog.sigfpe.com/2006/12/evaluating-cellular-automata-is.html</a> About using lazy, infinite containers for cellular automata.</p>
<p><a href="http://madeira.cc.hokudai.ac.jp/RD/takai/automa.html">http://madeira.cc.hokudai.ac.jp/RD/takai/automa.html</a> Graphics applications for cellular automata – lots of videos!</p>
<h3>Game Design</h3>
<p><a href="http://www.gamestudies.org/0102/pearce/">http://www.gamestudies.org/0102/pearce/</a> An article about game design.</p>
<p><a href="http://www.cp.eng.chula.ac.th/~vishnu/gameResearch/Sweetser_Thesis.pdf">http://www.cp.eng.chula.ac.th/~vishnu/gameResearch/Sweetser_Thesis.pdf</a> A thesis that looks at game design from a emergence perspective.</p>
<p><a href="http://fora.tv/2006/06/26/Will_Wright_and_Brian_Eno#chapter_01">http://fora.tv/2006/06/26/Will_Wright_and_Brian_Eno#chapter_01</a> Will Wright and Brian Eno on generative systems.</p>
<h2>Downloads</h2>
<h3>Game Maker Demos</h3>
<ul>
<li>Requires Game Maker 7.</li>
<li>Contains 9 demos.</li>
</ul>
<p><a href="http://www.code-spot.co.za/downloads/game_maker/ca_demos.zip">ca_demos.zip</a> (135 KB)</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fcode-spot.co.za%2F2009%2F04%2F09%2Fcellular-automata-for-simulation-in-games%2F&amp;linkname=Cellular%20Automata%20for%20Simulation%20in%20Games"><img src="http://code-spot.co.za/blog/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a>
<p><a href="http://feedads.g.doubleclick.net/~a/sjoqY1mUGuqOVdF-Hg52dk_oqNE/0/da"><img src="http://feedads.g.doubleclick.net/~a/sjoqY1mUGuqOVdF-Hg52dk_oqNE/0/di" border="0" ismap="true"></img></a><br/>
<a href="http://feedads.g.doubleclick.net/~a/sjoqY1mUGuqOVdF-Hg52dk_oqNE/1/da"><img src="http://feedads.g.doubleclick.net/~a/sjoqY1mUGuqOVdF-Hg52dk_oqNE/1/di" border="0" ismap="true"></img></a></p><img src="http://feeds.feedburner.com/~r/code-spot/~4/c_NirXyj_Kk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=cellular-automata-for-simulation-in-games</feedburner:origLink></item>
	</channel>
</rss>
