<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Algorithms and Stuff</title>
	<atom:link href="https://blog.ivank.net/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.ivank.net</link>
	<description>Algorithms and Stuff</description>
	<lastBuildDate>Wed, 25 Mar 2026 14:41:52 +0000</lastBuildDate>
	<language>en-US</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.8.38</generator>
	<item>
		<title>Mathematical foundation of music</title>
		<link>https://blog.ivank.net/mathematical-foundation-of-music.html</link>
		<comments>https://blog.ivank.net/mathematical-foundation-of-music.html#comments</comments>
		<pubDate>Sun, 06 Oct 2024 13:20:07 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=1187</guid>
		<description><![CDATA[Let&#8217;s discuss how the current music is created, and what was the motivation of the current system of musical tones. Sound is a vibration (e.g. of a string, of a drum, of a speaker &#8230;) which propagates through air, and can be detected e.g. by a human ear or by a microphone. It can not [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Let&#8217;s discuss how the current music is created, and what was the motivation of the current system of musical tones.</p>
<p><span id="more-1187"></span></p>
<p><b>Sound</b> is a vibration (e.g. of a string, of a drum, of a speaker &#8230;) which propagates through air, and can be detected e.g. by a human ear or by a microphone. It can not travel through the vacuum (in space), or through materials which absorb vibrations (like thick walls). The vibration gets weaker with the increasing distance from the source.</p>
<p>Vibration of the air means changes of the pressure of the air. These vibrations can be detected by a microphone and plotted on a chart. Zero value means silence, positive and negative values denote changes in pressure.</p>
<h2>Tones and Noises</h2>
<p>We distinguish <b>tones</b> (a spoon hitting a cup, a hammer hitting a metal rod) and <b>noises</b> (clapping hands, a hammer hitting a wall, sound of trees in the wind). The difference is, that when the sound is plotted on a chart, <b>tones have a small part, a &#8220;pattern&#8221;, that is repeating in time</b>. In other words, tones are <b>periodic</b>, while noises do not have any clear pattern which is repeating in time, the chart of the air pressure is more &#8220;random&#8221; for noises.</p>
<p>As we said, a tone is some sound pattern that is repeated in time. This pattern can be e.g. a single oscilation of a string. &#8220;A number of repetitions within a second&#8221; is called a <b>frequency</b> or a <b>pitch</b>, and is measured in Hertz. E.g. when a string makes 100 oscilations per second, we can hear a tone of 100 Hz.</p>
<h2>Combining tones</h2>
<p>When two or more tones sound at the same time, their pressure is &#8220;added&#8221; together, which corresponds to a chart of a sum of two mathematical functions. In music, we want two tones to sound &#8220;nice&#8221; when played together.</p>
<h3><i>Two tones sound nice together, if they create a periodic sound</i></h3>
<p>The goal of a musician is to find two or more tones, which, when combined, still create a tone (a periodic sound). The new sound may have a different repeating pattern, a different frequency, but it <b>must be periodic</b>. Let&#8217;s look at the properties of periodic functions.</p>
<h2>Periodic functions</h2>
<h3><i>If $f(x)$ and $g(x)$ have a period of T, then, $f(x)+g(x)$ has a period of T</i></h3>
<p>This is clear: if two instruments create a sound of the same pitch, it sounds nice, no matter what the intruments are, how loud they play, etc. From now on, it is clear, that we should not worry about a specific pattern of a tone, but only about its frequency.</p>
<h3><i>If $f(x)$ has a period of T, then, $f(x+c)$ has a period of T</i></h3>
<p>In other words, a &#8220;phase&#8221; is not important. We get that $f(x)+f(x+c)$ still has a period of T.</p>
<p>$sin(x)+sin(x+0.4)$</p>
<p><img border="0" src="http://www.ivank.net/graph/newgraph.php?highquality=1&#038;zoom=50&#038;height=200&#038;width=660&#038;func0=sin(x)plussin(xplus0.4)&#038;red1=255&#038;blue1=0&#038;green0=0"></p>
<h3><i>If $f(x)$ has a period of T, then, $f(nx)$ has a period of T for any integer $n$</i></h3>
<p>We make $n$ repetitions of the function within a single repetition of the original function. We can combine any tone with a tone of double frequency, tripple frequency, etc.</p>
<p>$sin(x)+sin(2x)$</p>
<p><img border="0" src="http://www.ivank.net/graph/newgraph.php?highquality=1&#038;zoom=50&#038;height=200&#038;width=660&#038;func0=sin(x)plussin(2*x)&#038;red1=255&#038;blue1=0&#038;green0=0"></p>
<p>Now we see, that a frequency of 200 Hz sounds nice with a frequency of 100 Hz. The ratio of frequencies is 2:1. We let the new function repeat twice, while the original function repeats once.</p>
<p>This is a handy mechanism for finding new frequencies that &#8220;sound nice&#8221; together. Let one function repeat m-times within a period, while another function repeats n-times within a period.<br />
<h3><i>If $f(x)$ has a period of T, then, $f(mx)+f(nx)$ has a period of T for any integers $m, n$</i></h3>
<p>$sin(3x)+sin(2x)$</p>
<p><img border="0" src="http://www.ivank.net/graph/newgraph.php?highquality=1&#038;zoom=50&#038;height=200&#038;width=660&#038;func0=sin(3*x)plussin(2*x)&#038;red1=255&#038;blue1=0&#038;green0=0"></p>
<p>In the example above, the ratio of frequencies is 3:2 (1.5). When we have a tone at some frequency (e.g. 300 Hz), we can play a tone with a frequency 1.5 times higher (450 Hz) and be sure that they sound nice together. The first tone must repeat twice, while the second repeats three times, to create a whole period &#8211; a repeating pattern of their sum.</p>
<p>Do 200 Hz and 307.7 Hz sound nice together? The ratio is 1.5385, or about 20:13. It requires 13 repetitions of the 200 Hz tone and 20 repetitions of 307.7 Hz to get to the whole period. When the period is so long, tones do not sound as nice together anymore. The goal of music is to find <b>ratios with a short period (small integers)</b>.</p>
<p>Let&#8217;s find some &#8220;nice&#8221; ratios between 1 and 2:</p>
<ul>
<li>1:1 &#8211; 1.0</li>
<li>9:8 &#8211; 1.125</li>
<li>5:4 &#8211; 1.25</li>
<li>4:3 &#8211; 1.3333</li>
<li>3:2 &#8211; 1.5</li>
<li>5:3 &#8211; 1.6666</li>
<li>15:8 &#8211; 1.875</li>
<li>2:1 &#8211; 2.0</li>
</ul>
<h2>Which tones should be used in music</h2>
<p>Let&#8217;s write down some requirements for the musical instrument</p>
<ul>
<li><b>some tone</b> &#8211; it must play at least one tone</li>
<li><b>nice ratios</b> &#8211; if it plays a tone, it would be nice to play a higher tone with a nice ratio (2:1, 3:2, 4:3 &#8230;)</li>
<li><b>flexibility</b> &#8211; if it plays a melody (a sequence of tones), it would be nice to be able to play the same melody a bit lower or a bit higher (e.g. each tone with 10% lower or 10% higher frequency)</li>
</ul>
<p>It is technically possible to make an instrument which plays any frequency (either when building it, or later, when cofiguring / tuning the instrument). We also want to be able to play several instruments at the same time. We must pick <b>a set of tones (frequencies), which all instruments must be able play</b>.</p>
<p>After centuries of evolution and new ideas, people came up with an incredibly elegant set of tones for the music. Here is how it is created:</p>
<ul>
<li>A tone of <b>27.5 Hz</b>, which is called A<sub>0</sub></li>
<li>From A<sub>0</sub>, create a sequence A<sub>1</sub>, A<sub>2</sub>, A<sub>3</sub> &#8230;, where each next tone is 2x higher (55 Hz, 110 Hz, 220 Hz, &#8230;)</li>
<li>As we have a geometric sequence of frequencies (55, 110, 220, &#8230;), split each step into <b>12 smaller, equal steps</b> (which still form a geometirc sequence)</li>
</ul>
<p>The last rule inserts 11 more tones in between $A_n$ and $A_{n+1}$. This sequence of tones has a beatiful property: each two consecutive tones have the same ratio: about 1.06 (precisely $2^\frac{1}{12}$).<br />
If we start at any tone (frequency) $t$, and repeat this small step twelve times, we will double the frequency: $t\cdot1.06^{12} = t\cdot2$.</p>
<p>We can redefine musical tones: A frequency $t$ is a musical tone if and only if there is an integer $n$, such that $t = 27.5 \cdot 2^\frac{n}{12}$ Hz.  We can denote such a tone as $t_n$.</p>
<ul>
<li> $t_0$ = 27.5 Hz = A<sub>0</sub> </li>
<li> $t_{24}$ = 110 Hz = A<sub>2</sub> </li>
<li> $t_{26} = t_{24} \cdot 1.06 \cdot 1.06 =$ 123.47 Hz</li>
<li> &#8230; </li>
</ul>
<p>A regular piano contains 88 keys, which play frequencies $t_0$ = A<sub>0</sub> = 27.5 Hz (left-most key) up to $t_{87}$ = 4186 Hz (right-most key). We can also see a pattern of 12 keys (7 white, 5 black), which repeats across the piano.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/2/2e/Piano_Frequencies.svg" style="width:100%" /></p>
<p>For historical reasons, musicans call this smallest step (a ratio of 1.06) a <b>semitone</b>, while the 12 semitones (a ratio of 2:1) is called an <b>octave</b>. A ratio between tones is called <b>an interval</b>.</p>
<p>Example: what is the difference between 150 Hz and 1200 Hz? A non-musician says it is 1050 Hz. A mathematician (after reading this article) can say, that it is a ratio of 8:1, or an interval of <b>three octaves</b>: $150\cdot2\cdot2\cdot2=1200$.</p>
<p>What is so elegant about this mechanism of choosing tones to be used in music? For every tone, it contains tones with nice ratios to the original tone!</p>
<table>
<tr>
<th>Ratio</th>
<th>Similar ratio in music</th>
</tr>
<tr>
<td>1:1 &#8211; 1.0    </td>
<td>exactly 0 semitones</td>
</tr>
<tr>
<td>9:8 &#8211; 1.125  </td>
<td>about 2 semitones: $2^\frac{2}{12}$ = 1.1224</td>
</tr>
<tr>
<td>5:4 &#8211; 1.25   </td>
<td>about 4 semitones: $2^\frac{4}{12}$ = 1.2599</td>
</tr>
<tr>
<td>4:3 &#8211; 1.3333 </td>
<td>about 5 semitones: $2^\frac{5}{12}$ = 1.3348</td>
</tr>
<tr>
<td>3:2 &#8211; 1.5    </td>
<td>about 7 semitones: $2^\frac{7}{12}$ = 1.4983</td>
</tr>
<tr>
<td>5:3 &#8211; 1.6666 </td>
<td>about 9 semitones: $2^\frac{9}{12}$ = 1.6817</td>
</tr>
<tr>
<td>15:8 &#8211; 1.875 </td>
<td>about 11 semitones: $2^\frac{11}{12}$ = 1.8877</td>
</tr>
<tr>
<td>2:1 &#8211; 2.0    </td>
<td>exactly 12 semitones</td>
</li>
</table>
<p>Besides the same tone (1:1) and an octave (2:1), we could say that the ratio of 3:2 is the <b>most beautiful</b>: the integers are small (2 repetitions and 3 repetitions within a period)<br />
and the musical tones can approximate it almost perfectly with 7 semitones: $\frac{t_{n+7}}{t_{n}} \doteq \frac{3}{2}$.</p>
<h3>A (very simplified) history of note names</h3>
<p>Thousands of years ago, there was an instrument, that could play 14 tones across two octaves. Centuries later, these tones were named A, B, C, D, E, F, G, a, b, c, d, e, f, g. </p>
<p>Centuries later, there was another instrument with 7 tones within an octave, ant the tones were named do, re, mi, fa, sol, la, si. The first tone <b>do</b> could have any frequency, but <b>mi to do</b> must be 5:4, <b>fa to do</b> must be 4:3, <b>sol to do</b> must be 3:2, and others &#8220;somewhere in between&#8221;. Since <b>do</b> was often tuned to the same frequency as <b>C</b> of the older instrument, these seven notes were also called C, D, E, F, G, A, B. A piano of that time contained seven keys within an octave.</p>
<p>Many years later, people noticed, that an octave can be separated into <b>12 equal steps</b>. It would still contain &#8220;nice intervals&#8221; (5:4, 4:3, 3:2, 2:1, &#8230;), but it would offer <b>flexibility</b> &#8211; a music piece can be shifted: played several semitones higher or lower.<br />
In this new model, &#8220;old notes&#8221; C, D, E, F, G, A, B, correspond to +0, +2, +4, +5, +7, +9 and +11 semitones. But we need to make five more notes (+1, +3, +6, +8, +10) availabe on the instrument &#8211; so the black keys were added on a piano. These new notes need some names. We could name them e.g. H, I, J, K and L. Since a symbol # is used to shift a tone one semitone higher, it makes sense to name them C#, D#, F#, G# and A#. Here we see these twelve notes on a modern piano keyboard.</p>
<p><img src="//i.imgur.com/kAGKMeO.png" /></p>
<p>As there used to be 7 notes within an octave, it lead to naming certain intervals (frequency ratios) in a specific way.</p>
<table>
<tr>
<th>Step  </th>
<th>as semitones</th>
<th>English</th>
<th>Italian</th>
</tr>
<tr>
<td>C to C</td>
<td>0 semitones </td>
<td>First (unison)</td>
<td>Prima</td>
</tr>
<tr>
<td>C to D</td>
<td>2 semitones </td>
<td>Second </td>
<td>Seconda</td>
</tr>
<tr>
<td>C to E</td>
<td>4 semitones </td>
<td>Third  </td>
<td>Terza</td>
</tr>
<tr>
<td>C to F</td>
<td>5 semitones </td>
<td>Fourth </td>
<td>Quarta</td>
</tr>
<tr>
<td>C to G</td>
<td>7 semitones </td>
<td>Fifth  </td>
<td>Quinta</td>
</tr>
<tr>
<td>C to A</td>
<td>9 semitones </td>
<td>Sixth  </td>
<td>Sesta</td>
</tr>
<tr>
<td>C to B</td>
<td>11 semitones</td>
<td>Seventh</td>
<td>Settima</td>
</tr>
<tr>
<td>C to C</td>
<td>12 semitones</td>
<td>Eighth (octave)</td>
<td>Ottava</td>
</tr>
</table>
<p>Now, we know the origin of a confusing word <b>octave</b>, which implies a number 8, but there is no 8 in a ratio of 2:1, or 12 semitones. Similarly, a word <b>fifth (quinta)</b> implies a number 5, but there is no 5 in a ratio of 3:2, or in 7 semitones.</p>
<h3>All tones that exist</h3>
<p>Let&#8217;s write down all musical tones (frequencies) that exist (that are ever used in music). Since frequencies below 20 Hz and above 10,000 Hz are almost impossile to hear, and there must be at least 6% difference between two frequencies, we can use only around 100 different tones in music.</p>
<p><img src="//i.imgur.com/Kgmj1NS.png" style="width:100%" /> <!-- source: https://jsfiddle.net/mp75n13f/3/ --></p>
<p>As we can see, 1000 Hz is never used in music. We can either use B5 (987.77 Hz), or C6 (1046.5 Hz), but playing or singing a tone of 1000 Hz would be considered out of tune &#8211; it never sounds nice with any other musical tones.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/mathematical-foundation-of-music.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How Vector Graphics Work</title>
		<link>https://blog.ivank.net/how-vector-graphics-work.html</link>
		<comments>https://blog.ivank.net/how-vector-graphics-work.html#comments</comments>
		<pubDate>Fri, 31 Jan 2020 20:13:00 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[computer graphics]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=1137</guid>
		<description><![CDATA[I have worked with vecor graphics for more than 15 years, but some mechanisms were not clear to me. Now, I think I have figured it out and I would like to explain it to you. Vector graphics usually consists of points, which are connected with straight or curved lines (Bézier curves, circular arcs). Together, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I have worked with vecor graphics for more than 15 years, but some mechanisms were not clear to me. Now, I think I have figured it out and I would like to explain it to you.</p>
<p><span id="more-1137"></span></p>
<p>Vector graphics usually consists of points, which are connected with straight or curved lines (Bézier curves, circular arcs). Together, they define a contour of some shape. There are commands, which have several arguments. They describe the movement of a virtual pen. E.g. moveTo (M:2), lineTo (L:2), curveTo (C:6), arcTo (A:7) and closePath (Z:0), which let us define points of the contour and connections between these points.</p>
<p>A path consists of any number of these commands in any order. If we take any path and shuffle the commands randomly, it still defines a valid path.</p>
<pre>M 0 0  L 5 0  L 5 5  L 0 5  Z  -- drawing a square
L 5 5  L 5 0  Z  M 0 0  L 0 5  -- randomly shuffled, but still a valid path
</pre>
<p>Such sequence of commands can be stroked or filled with a color. The <b>filling mechanism</b> is the most misunderstood part. It is clear, that if we fill a circle or a square, we will get a circle or a square. But many cases are not clear at all.</p>
<ul>
<li>When one shape intersects another, will the intersection be filled or not?</li>
<li>When a shape intersects itself, will the intersection be filled or not?</li>
<li>When I make a small circle inside a big one, will it cut a hole or do nothing?</li>
<li>Does it matter, if I draw a big circle first and a smaller after, or a small one first?</li>
<li>Does it matter, if a contour is drawn in a clockwise or anti-clockwise direction, when making holes?</li>
<li>What are the fill orders like &#8220;evenodd&#8221; and &#8220;nonzero&#8221;? Are they boolean operations?</li>
</ul>
<h2>The Example</h2>
<p>These mechanisms of filling vector shapes were defined in 60s and 70s, and probably will be used for many centuries. They are used in many standards (pretty much everywhere where vector graphics is used):</p>
<ul>
<li>SVG</li>
<li>HTML5 Canvas</li>
<li>PostScript, EPS and PDF</li>
<li>OpenType and TrueType fonts</li>
<li>Flash Player and ActionScript programming</li>
<li>Adobe Photoshop, Illustrator, XD, Sketch App, Figma</li>
</ul>
<p>Let&#8217;s demonstrate our explanation on a specific example. For simplicity, let&#8217;s just use polygons (no curves).</p>
<p><img src="https://i.imgur.com/pAFEFUq.png" style="width:50%" /></p>
<pre>SVG code: M 100 100 L 360 100 L 200 300 L 200 200 L 360 400 L 100 400 Z
M 50 50 L 150 50 L 150 150 L 50 150 Z  
M 50 200 L 50 300 L 150 300 L 150 200 Z
M 120 320 L 180 320 L 180 380 L 120 380 Z  
M 220 320 L 220 380 L 280 380 L 280 320 Z 
M 120 120 L 120 180 L 180 180 L 180 120 Z</pre>
<p><a href="https://jsfiddle.net/6ebmsfk5/" target="_blank">Run SVG</a></p>
<p>First, we drew a shape, that looks like a letter &#8220;K&#8221; (a polygon with six points). Then, we drew two large squares.<br />
And then, three small squares. The direction of drawing is visualized by red arrows.<br />
Now, we tell the computer to fill this shape. Can you determine, which parts will be filled, and which will remain empty?</p>
<h2>The Solution</h2>
<p>At the beginning, there is a large infinite plane. Our drawing &#8220;cuts&#8221; the plane into multiple <b>parts</b>. There is a large infinite part on the outside, and many smaller, finite parts. It is not possible to get from one part to another without crossing a line (contour). In our example, there are <b>11 parts</b>. Now, we have to give a number, a <b>rank</b>, to each part (and to all points inside that part).</p>
<p>At the beginning, the empty area has a rank 0. When a shape is drawn <b>clockwise</b>, all points inside that shape have a rank increased by 1. Similarly, when it is drawn anti-clockwise, all points inside it have a rank decreased by 1.</p>
<p>Imagine two intersecting circles, drawn clockwise (four parts). The outer area has a rank 0, their intersection has a rank 2, and the two remaining parts have a rank 1. If a second circle was drawn anti-clockwise, their intersection would have a rank 0, and the rest of the second circle would have a rank -1.</p>
<p><b>Alternative definition.</b> Put your finger (or a pen) into a specific part, and set a counter to zero. Now, drag it outside (to the infinite part). Each time you cross a contour &#8220;going right&#8221;, increase the counter by 1, and each time you cross a contour &#8220;going left&#8221;, decrease the counter by 1. At the end, you will get the rank of that part, in which you started. Fun fact: it does not matter in which direction you go, or how many contours you cross, you will always get the same number.</p>
<p>Let&#8217;s determine ranks for our vector shape.</p>
<p><img src="https://i.imgur.com/yFSmhpn.png" style="width:50%" /></p>
<p>Now, the solution is very simple: if we fill a shape with the <b>nonzero</b> rule, only parts with non-zero rank will be filled(&#8230;-3, -2, -1, 1, 2, 3, ..). If we use the <b>evenodd</b> rule, only parts with odd rank will be filled (&#8230; -3, -1, 1, 3, 5, &#8230;).</p>
<p><img src="https://i.imgur.com/pmDD4B9.png" /></p>
<p>Knowing this, we can deduce several properties:</p>
<ul>
<li>The order, in which we draw contours, is not important (as it does not change the final rank of each part).</li>
<li>Reversing all contours (CW to ACW and ACW to CW) is not important (it will change every rank R to -R, but both fill rules will work identically)</li>
<li>If we use the &#8220;evenodd&#8221; rule, the direction of drawing is not important (if we reverse any contour, it will add 2 or subtract 2 from all ranks inside it, but does not change the &#8220;oddness&#8221;)</li>
</ul>
<h2>An Important Note</h2>
<p>We described our mechanism in a plane, where the X axis goes right, and the Y axis goes down. When Y goes up, the terms clockwise and anti-clockwise (and also left and right) are exchanged. Points (0,0), (100,0), (50,50) make a triangle going clockwise when Y goes down, or anti-clockwise when Y goes up. But this triangle always has a rank 1, so it is always filled the same way (i.e. only the coordinates define how a shape is filled, not where axes go).</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/how-vector-graphics-work.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Symmetry Breaking in Automated Planning</title>
		<link>https://blog.ivank.net/symmetry-breaking-in-automated-planning.html</link>
		<comments>https://blog.ivank.net/symmetry-breaking-in-automated-planning.html#comments</comments>
		<pubDate>Sun, 26 Mar 2017 21:50:25 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=1064</guid>
		<description><![CDATA[This is my master thesis about exploiting structures in automated planning (through symmetry breaking). You can read it here: Exploiting structures in automated planning. The domains and problems, that were used for testing, are here: Domains. Symmetry breaking Several ways of symmetry breaking have been proposed for automated planning in the past. I decided to [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>This is my master thesis about exploiting structures in automated planning (through symmetry breaking). You can read it here: <big><a href="//www.ivank.net/blogspot/symmetry_breaking.pdf" target="new">Exploiting structures in automated planning</a></big>. The domains and problems, that were used for testing, are here: <a href="//www.ivank.net/blogspot/domains.zip">Domains</a>.</p>
<p><span id="more-1064"></span></p>
<h2>Symmetry breaking</h2>
<p>Several ways of symmetry breaking have been proposed for automated planning in the past. I decided to propose a new set of definitions, which may give a new look at the problem of symmetries in automated planning.</p>
<p>I focused at the <b>relational representation</b> of a planning problem, i.e. the representation, where the state is a set of atoms of specific predicates. Such state can be also viewed as a set of relations, when atoms are &#8220;grouped together&#8221; by their predicates. This is quite natural way of analyzing a planning problem, since it resembles the PDDL format.</p>
<p>It is shown, that symmetries can be generated by automorphisms of a relational state. Detecting such automorphisms is the key to pruning the state-space search. Instead of making a general automorphism detection, I present a simple algorithm for detecting a specific class T1 (subgroup of the group of automorphisms), which is very frequent in many planning domains. A simple state-space search algorithm can be extended by this method and improve the performance.</p>
<h2>Orbit Search</h2>
<p>At the end, I showed, that such symmetry breaking is less general than <a href="http://icaps11.icaps-conference.org/proceedings/hdip/pochter-et-al.pdf" target="new">Orbit Search</a>, i.e. every relational symmetry, that is generated by a relational automorphism, is also a symmetry of the &#8220;standard&#8221; SAS+ representation of the same problem and can be detected by algorithms based on the Orbit Search. In my experiments, the Metis planner (based on Orbit Search) always visits the smaller number of states than my experimental planner PLANR. Despite this, PLANR is sometimes faster than Metis.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/symmetry-breaking-in-automated-planning.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Viterbi Algorithm Clarified</title>
		<link>https://blog.ivank.net/viterbi-algorithm-clarified.html</link>
		<comments>https://blog.ivank.net/viterbi-algorithm-clarified.html#comments</comments>
		<pubDate>Thu, 02 Jun 2016 23:32:36 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[Math]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[probability]]></category>
		<category><![CDATA[viterbi]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=1004</guid>
		<description><![CDATA[All articles about Vitebi algorithm, which I found, seemed too complicated and hard to understand. They either had too much theory and no examples, or too complex example without an abstract description. I will try to write a my own article and clarify things a little. Defining a problem It is hard to understand something [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>All articles about Vitebi algorithm, which I found, seemed too complicated and hard to understand. They either had too much theory and no examples, or too complex example without an abstract description. I will try to write a my own article and clarify things a little.</p>
<p><span id="more-1004"></span></p>
<h2>Defining a problem</h2>
<p>It is hard to understand something without knowing the exact purpose. Let&#8217;s sketch a specific problem and talk about possible solutions.</p>
<p>You are a doctor in a little town. There is a patient, who visited you for 3 days in a row. To simplify things a bit, the patient can be in one of 2 states: (Healthy, Fever) and he can tell you 3 feelings: (Normal, Cold, Dizzy). During these 3 days, he told you, that he feels Normal (1st day), Cold (2nd day), Dizzy (3rd day).</p>
<p>You also have some scientific results, which can help you guess the state of the patient:</p>
<ul>
<li><b>Start</b>: in general, 60% of people are Healthy, 40% have Fever</li>
<li><b>Transition</b>:
<ul>
<li>when Healthy, there is 70% chance of remaining Healthy the next day (30% chance of Fever)</li>
<li>when Fever, there is 40% chance of becoming Healthy the next day (60% chance of Fever)</li>
</ul>
</li>
<li><b>Emission</b>:
<ul>
<li>when Healthy, he reports: 50% Normal, 40% Cold, 10% Dizzy</li>
<li>when Fever, he reports: 10% Normal, 30% Cold, 60% Dizzy</li>
</ul>
</li>
</ul>
<p>Given the specific 3-day observation <b>(Normal, Cold, Dizzy)</b>, we must find the most probable real state in each day. It could be (Fever,Fever,Fever), or (Healthy,Healthy,Fever) etc. For 3 days and 2 possible real states, there are $2^3=8$ possible triples. We can&#8217;t know the real state of the patient, all we can do is finding a good guess &#8211; most probable triple of states.</p>
<h2>Naive approach</h2>
<p>What is the chance, that the patient was (Healthy,Fever,Fever)? The chance of Healthy on the 1st day is 60% (Start probability), Fever on the 2nd day is 30% (transition Healthy->Fever) and Fever on the 3rd day is 60% (transition Fever->Fever). The total probability of (Healthy,Fever,Fever) is $0.6 \cdot 0.3 \cdot 0.6 = 0.108$. If we compute probabilities of all triples of states (which must sum up into 1), we will see, that the most probable is (Healthy,Healthy,Healthy), which has the probability $0.6 \cdot 0.7 \cdot 0.7 = 0.294$.</p>
<p>Such results hold for anybody in town, we completely ignore our observations. Let&#8217;s compute the new probability, while taking observations into account:</p>
<p>What is the chance, that patient was (Healthy,Fever,Fever), when reporting (Normal,Cold,Dizzy)? The chance of Healthy on the 1st day + reporting Normal when healthy is 60% x 50%. The chance of Fever on the 2nd day + reporting Cold is 30% x 30%. The chance of Fever on the 3rd day + reporting Dizzy is 60% x 60%. In total, the probability of (Healthy,Fever,Fever) is $ (0.6\cdot 0.5) \cdot (0.3 \cdot 0.3) \cdot (0.6 \cdot 0.6) = 0.00972 $.</p>
<p>If we compute probabilities of all triples of states, we will see, that <b>the most probable is (Healthy,Healthy,Fever)</b> with probability $ (0.6\cdot 0.5) \cdot (0.7 \cdot 0.4) \cdot (0.3 \cdot 0.6) = 0.01512 $. Why are the values so small? Will they sum up to 1? These are probabilities of a specific state AND a specific observation. They will sum up to the probability of that observation.</p>
<p>Our problem is very easy to solve. We just compute the probabilities of each possible real states and choose the most probable one. The problem is, that when we are observing the patient for 10 days, there are $2^{10}=1024$ possible tuples of states, that we must examine. And for 100 days, it seems almost impossible to solve.</p>
<h2>Smart approach (Viterbi algorithm)</h2>
<p>The smart solution of our problem is based on dynamic programming. For each day and each state (Healthy or Fever) we will compute the most probable paths (sequences of Healthy / Fever and probabilities) for geting into that state on that day (. Let&#8217;s calculate it for the first day.</p>
<p>Observation: <b>(Normal, Cold, Dizzy)</b></p>
<table>
<tr>
<th>Day:</th>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
<tr>
<td>Healthy</td>
<td>0.6*0.5=0.3 (H &#038; Normal)</td>
<td></td>
<td></td>
</tr>
<tr>
<td>Fever</td>
<td>0.4*0.1=0.04 (F &#038; Normal)</td>
<td></td>
<td></td>
</tr>
</table>
<h3>The basic principle</h3>
<p>The Viterbi algorithm is based on an observation, that the optimal path to each day (and each state) can be easily deduced from the optimal path to the previous day (and each state). </p>
<p>What is the &#8220;most probable scenario&#8221; to being Healthy on the 2nd day? We can deduce it from the previous day! If we were Healthy on the 1st day, we remain Healthy witht the probability: </p>
<pre>(H before) * (H->H) * (H &#038; Cold) = 0.3 * 0.7 * 0.4 = 0.084.</pre>
<p>If we had Fever on the 1st day, we are Healthy with the probability:</p>
<pre>(F before) * (F->H) * (H &#038; Cold) =  0.04 * 0.4 * 0.4 = 0.0064. </pre>
<p>The bigger value is 0.084, so the most probable scenario to being Halthy on the 2nd day is being Healthy on the 1st day.</p>
<p>What about Fever on the 2nd day?</p>
<pre>(H before) * (H->F) * (F &#038; Cold) = 0.3 * 0.3 * 0.3 = 0.027.  
(F before) * (F->F) * (F &#038; Cold) = 0.04 * 0.6 * 0.3 = 0.0072. </pre>
</p>
<p>The maximum is 0.027 (the patient was probably Healthy the day before). Let&#8217;s fill the whole table using that method.</p>
<table>
<tr>
<th>Day:</th>
<th>1</th>
<th>2</th>
<th>3</th>
</tr>
<tr>
<td>Healthy</td>
<td>0.3 </td>
<td>0.084 (>0.0064)</td>
<td> 0.00588 (>0.00108) </td>
</tr>
<tr>
<td>Fever</td>
<td>0.04</td>
<td>0.027 (>0.0072)</td>
<td> 0.01512 (>0.00972) </td>
</tr>
</table>
<p>In order to reconstruct the optimal path, we must remember the previous value, that was chosen for each day and each state (the one that yielded the maximum probability). The maximum value (the most probable state) for the third day is Fever, it was computed from Healthy on the 2nd day, which was computed from Healthy on the 1st day, so the optimal path is (Healthy,Healthy,Fever).</p>
<h2>Generalization</h2>
<p>How would the algorithm work, if there were more possible states (Healthy, Fever, Disease1, Disease2 &#8230;) or more possible observations (Normal, Cold, Dizzy, Shaking, Nausea, Headache)? The transition and emission tables would be much larger. We would have to go through more values when computing each column of our table. But the principle would be the same.</p>
<p>For T days and K possible states, algorithm computes T columns of the table, K cells in each column. For each cell, it analyzes K cells in the previous column to find the best one. The algorithm takes time $\Theta (T \cdot K^2)$. The final selection of the path in time T fits into our complexity.</p>
<h2>Other examples</h2>
<p>Let&#8217;s make an autocorrect program. When user types &#8220;toqer&#8221; into computer, we will offer him to change it into &#8220;tower&#8221;, because he probably misprinted the letter &#8220;Q&#8221;, which is near the letter &#8220;W&#8221; on the keyboard.</p>
<p>Instead of true health states and feelings, we will have the letters of the alphabet. Instead of guessing the true health state for 5 days, we will be guessing the true 5-letter word, that user had in his mind (unknown). The 5-day observation is the 5-letter word, which user actually typed on the keyboard (toqer).</p>
<ul>
<li>Start: the probability, that some letter is the first letter of some English word (26 values).</li>
<li>Transiton: probabilities, e.g. that the letter O will be followed by letter Q, etc (26 x 26 values).</li>
<li>Emission: probabilities, that user has typed what he wanted to type. E.g. when user wants to type F, he types F in 90%, G in 4% (because it is near F on the keyboard), etc (26 x 26 values).</li>
</ul>
<p>The start and transition probability can be obtained by analyzing some large amount of English text, Emission table can be created manually.</p>
<p>When observing the word &#8220;toqer&#8221;, we can compute the most probable &#8220;true word&#8221; using Viterbi algorithm in the same way we used it earlier, and get the true word &#8220;tower&#8221;. Viterbi algorithm can be used for solving many classes of problems, which seem to be completely unrelated at the first sight.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/viterbi-algorithm-clarified.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Monty Hall problem makes no sense, or does it?</title>
		<link>https://blog.ivank.net/monty-hall-problem-makes-no-sense-or-does-it.html</link>
		<comments>https://blog.ivank.net/monty-hall-problem-makes-no-sense-or-does-it.html#comments</comments>
		<pubDate>Sat, 31 Oct 2015 15:18:38 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=958</guid>
		<description><![CDATA[It has been 8 years since I heard about Monty Hall problem for the first time. I never completely trusted the offical solution. The only solution I would completely trust is my own simulation of thousands of games, so I decided to make one and prove the rest of the world wrong. Here is a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>It has been 8 years since I heard about Monty Hall problem for the first time. I never completely trusted the offical solution. The only solution I would completely trust is my own simulation of thousands of games, so I decided to make one and prove the rest of the world wrong.</p>
<p><span id="more-958"></span></p>
<p><script type="text/javascript" src="//www.ivank.net/blogspot/montyhall.js"></script></p>
<p>Here is a description of a problem from Wikipedia:</p>
<p><i>Suppose you&#8217;re on a game show, and you&#8217;re given the choice of three doors: Behind one door is a car; behind the others, goats. You pick a door, say No. 1, and the host, who knows what&#8217;s behind the doors, opens another door, say No. 3, which has a goat. He then says to you, &#8220;Do you want to pick door No. 2?&#8221; Is it to your advantage to switch your choice?</i></p>
<h2>Simulation</h2>
<p>Let me start writing a Javascript code, each part will be previously explained. My simulation will start in a function <code>go</code>, which will call <code>montyHall</code> many times. montyHall has a <code>mode</code> parameter, which can control the decision strategy. montyHall returns 1 when player wins, and 0 when player loses.</p>
<pre name="dlhl" class="js">
function go()
{
    for(var m=0; m<4; m++)
    {
        var lim = 100000, sum = 0;
        for(var i=0; i&lt;lim; i++)  sum += montyHall(m);
        console.log(sum/lim);
    }
}</pre>
<p>Let's implement the <code>montyHall</code> function. Let's put the car behind a random door (0, 1, 2) and make a player pick a random door (0, 1, 2).</p>
<pre name="dlhl" class="js">
function montyHall(mode)
{
    var car = Math.floor(Math.random()*3);
    var me = Math.floor(Math.random()*3);
    //... revealing one goat
    //... maybe changing the value of "me"
    return car == me ? 1 : 0;
}</pre>
<p>After placing the car randomly, let's put two goats (variables <code>g0, g1</code>) behind the remaining doors and reveal one of them.</p>
<pre name="dlhl" class="js">
var g0, g1;
if(car==0) { g0=1; g1=2; }
if(car==1) { g0=0; g1=2; }
if(car==2) { g0=0; g1=1; }

var open = Math.random()<0.5 ? g0 : g1;
var pme = me;</pre>
<p>We also stored users previous decision into <code>pme</code>. Now, knowing an open door with a goat (<code>open</code>) and our former choice (<code>pme</code>), we have to make a new decision (a new value of <code>me</code>).</p>
<h3>Mode 0</h3>
<p>In this mode, we just keep our previous decision.</p>
<pre name="dlhl" class="js">
me = pme;</pre>
<h3>Mode 1</h3>
<p>In this mode, we change our choice randomly to one of two "unchosen" doors. It is one of the ways how I used to understand a problem.</p>
<pre name="dlhl" class="js">
if(pme==0) me = Math.random()<0.5 ? 1 : 2;
if(pme==1) me = Math.random()<0.5 ? 0 : 2;
if(pme==2) me = Math.random()<0.5 ? 0 : 1;</pre>
<h3>Mode 2</h3>
<p>In this mode, we change our choice randomly to one of two still closed doors. It is another way to understand a problem.</p>
<pre name="dlhl" class="js">
if(open==0) me = Math.random()<0.5 ? 1 : 2;
if(open==1) me = Math.random()<0.5 ? 0 : 2;
if(open==2) me = Math.random()<0.5 ? 0 : 1;</pre>
<h3>Mode 3</h3>
<p>Previous methods were aware of either open door, or previously chosen doors, not both at the same time. Let's choose a door, that is still closed, but different from our previous choice.</p>
<pre name="dlhl" class="js">
if(pme!=0 &#038;&#038; open!=0) me = 0;
if(pme!=1 &#038;&#038; open!=1) me = 1;
if(pme!=2 &#038;&#038; open!=2) me = 2;</pre>
<h3>Results</h3>
<table>
<tr>
<th>Mode</th>
<th>Win Probability</th>
<th>Comment</th>
</tr>
<tr>
<td>Mode 0</td>
<td>1/3</td>
<td>Keeping the original choice</td>
</tr>
<tr>
<td>Mode 1</td>
<td>1/3</td>
<td>Random of two "unchosen" doors (may be open)</td>
</tr>
<tr>
<td>Mode 2</td>
<td>1/2</td>
<td>Random of two closed doors (may be the previous one)</td>
</tr>
<tr>
<td>Mode 3</td>
<td>1/2</td>
<td>Choosing the closed door, that is different from our previous choice</td>
</tr>
</table>
<p><button onclick="go()" style="padding:0.5em; margin-bottom:1em">Run the simulation</button></p>
<p>As we can see, just changing our choice (Mode 1) does not change the probability (still 1/3). But if we choose different door, which is sitll closed, it is 1/2. But the correct answer is said to be 2/3, so did we prove the whole world wrong?</p>
<h2>Correct simulation</h2>
<p>Modes 1 and 2 in our previous simulation seem to be strange, since they ignore one of known facts. But Mode 3 should fix it. But according to "current science", changing our choice to another closed door should let us win 2/3 of the time. So is our decission procedure in Mode 4 still wrong? No. The way of revealing a goat is wrong.</p>
<p>By revealing one of goats, the host tells us much more, than just pointing out two possible positions of the car with 50:50 chance. There are 2 important rules, that are not pronounced directly and may not be obvious to everyone.</p>
<ul>
<li><b>The host must always open the door that was not picked by the contestant.</b></li>
<li><b>The host must always open the door to reveal a goat and never the car.</b></li>
</ul>
<p>Note, that in our previous implementation, the host could open the door chosen by the contestant (which violates the first rule). With these rules in mind, let's remake the way we open the door, while keeping all the code as it is. If we have chosen the car, the host will randomly open one of goats.</p>
<pre name="dlhl" class="js">
var open;
if(me==car) open = Math.random()<0.5 ? g0 : g1;</pre>
<p>Otherwise, there is just one possible way to open the door (the host can not open the car or the door chosen by us, and since both these door are different, just one door with a goat remains).</p>
<pre name="dlhl" class="js">
else
{
    if(me!=0 &#038;&#038; car!=0) open = 0;
    if(me!=1 &#038;&#038; car!=1) open = 1;
    if(me!=2 &#038;&#038; car!=2) open = 2;
}</pre>
<p>When there is a car behind our door at the beginning (33% chance), the host reveals the goat, we choose another closed door (the goat) and we lose. But when we choose the door with a goat at the beginning (66% chance), the host reveals the second goat and the other closed door must contain the car - we win.</p>
<h3>Results</h3>
<table>
<tr>
<td>Mode 0</td>
<td>1/3</td>
<td>Keeping the original choice</td>
</tr>
<tr>
<td>Mode 1</td>
<td>1/3</td>
<td>Random of two "unchosen" doors (may be open)</td>
</tr>
<tr>
<td>Mode 2</td>
<td>1/2</td>
<td>Random of two closed doors (may be the previous one)</td>
</tr>
<tr>
<td>Mode 3</td>
<td><b>2/3</b></td>
<td>Choosing the closed door, that is different from our previous choice</td>
</tr>
</table>
<p><button onclick="goCorrect()" style="padding:0.5em; margin-bottom:1em">Run the simulation</button>  </p>
<p><a href="//www.ivank.net/blogspot/montyhall.js">JS Code</a></p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/monty-hall-problem-makes-no-sense-or-does-it.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Introduction to Metamath</title>
		<link>https://blog.ivank.net/introduction-to-metamath.html</link>
		<comments>https://blog.ivank.net/introduction-to-metamath.html#comments</comments>
		<pubDate>Sun, 23 Aug 2015 17:39:02 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=889</guid>
		<description><![CDATA[Official Metamath description has 211 pages. This is a &#8220;shrinked&#8221; version, which does not contain introduction to logic, history of logic, definitions and statements, that mathematicians and computer scientists are already familiar with. Explore it in MM Tool. Having a formal (precise) system for mathematical theories and proofs is useful in many ways. Formal proof [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Official Metamath description has 211 pages. This is a &#8220;shrinked&#8221; version, which does not contain introduction to logic, history of logic, definitions and statements, that mathematicians and computer scientists are already familiar with. Explore it in <a href="http://mm.ivank.net" target="new">MM Tool</a>.</p>
<p><span id="more-889"></span></p>
<p>Having a formal (precise) system for mathematical theories and proofs is useful in many ways. Formal proof can be mechanically verified, which eliminates the risk of errors. And if we want a computer to work with our theories and proofs, having an exact precise system is the only way to do it.</p>
<h2>Core of Metamath</h2>
<p>Metamath is a language for defining a <strong><a href="https://en.wikipedia.org/wiki/Formal_grammar" target="new">formal grammar</a></strong>. We define terminal and nonterminal symbols, initial words and production rules. It is also possible to include a word and a sequence of rules, which generate that word, inside a Matamath file. For such word, we can mechanically verify, if it is really generated by our grammar (by processing a sequence of production rules, substituting symbols and comparing the final word with a claimed word). We do it using a <code>$p</code> statement (described below). Since Metamath is a language for defining grammars, there is no Math included. Metamath does not know what &#8220;+&#8221; or &#8220;=&#8221; or a bracket is.</p>
<h2>Metamath for Math</h2>
<p>Mathematicians use Metamath language to represent mathematics formally. We can define axioms and inference rules as production rules of a formal grammar. A language (a set of words), generated by this grammar, corresponds to a set of theorems, provable inside our theory (valid facts). And thanks to <code>$p</code> statements, we can include theorems and formal proofs of these theorems in our files. The grammar approach to proving may seem cumbersome, as proofs are usually quite long, but it elegantly deals with infinitely many axioms (e.g. induction in PA), many possible inference rules (Modus Ponens, resolution) etc.</p>
<p>Since Metamath was made to be used for Mathematics, the content of Metamath files is usually described in terms of predicate logic, instead of terms of the grammar theory.</p>
<h2>Metamath syntax</h2>
<p>Let&#8217;s describe a parsing algorithm. Only printable ASCII characters can be used in Metamath file. Metamath file is a sequence of tokens. A <b>token</b> consinsts of non-white-space characters, tokens are separated by one or more white-space characters (space, new line, tabulator). A following line contains 12 tokens:</p>
<pre name="dlhl">  $c  hello  hi  bar 0  \phi  ->  $.  $( ( __  $)  </pre>
<p><code>1 + 1</code> contains 3 tokens, while <code>1+1</code> contains just one token.</p>
<p>There are two types of tokens:</p>
<ul>
<li>tokens that start with <b>$</b>: Metamath tokens</li>
<li>tokens that don&#8217;t start with $: user-defined tokens</li>
</ul>
<p>The previous example contains four Metamath tokens and the rest are user-defined tokens. Let&#8217;s describe the meaning of Metamath tokens.<br />
As we &#8220;grouped&#8221; characters into tokens, we can group tokens into statements. A statement usually starts and ends with a Metamath token.</p>
<h3>$( statement</h3>
<pre>$( tok tok tok  $)</pre>
<p>Starts with <code>$(</code>, ends with <code>$)</code>. These statements are used to insert <strong>comments</strong>. They may occur anywhere in a Metamath file. Now, let&#8217;s suppose, that we have removed all comments from a Metamath file. Each of the remaining statements is one of the statements below.</p>
<h3>$c statement</h3>
<pre>$c ->  +  -  (  )  $.</pre>
<p>These statements are used to define <strong>terminal symbols</strong> of a grammar. Terminal symbols are called <strong>constants</strong> in Metamath community (don&#8217;t confuse with constants from logic). Constants don&#8217;t have to be defined all in one statement. You can define them at any part of a Metamath file.</p>
<h3>$v statement</h3>
<pre>$v A B C a b c phi \psi $.</pre>
<p>These statements are used to define <strong>nonterminal symbols</strong> of a grammar. Nonterminal symbols are called <strong>variables</strong> in Metamath community (don&#8217;t confuse with variables from logic). Variables don&#8217;t have to be defined all in one statement. You can define them at any part of a Metamath file.</p>
<p>A <b>word</b> is a sequence of constants and variables (i.e. terminals and nonterminals). In Metamath, we are interested in all words, generated by the grammar (i.e. not only words made out of terminals).</p>
<h3>$d statement</h3>
<pre>$d vToken vToken ... vToken $.</pre>
<p><strong>Disjoint variable restrictions</strong>. <code>vToken</code> must be a previously defined variable. For any two variables A and B from $d statement, when A and B occur together in some word, then sub-words (that are derived from A and from B) should never have any variables in common.</p>
<p>These restrictions are used to introduce the concept of variable substitutability in a comfortable way. E.g. when we have a word A < B and we don't want both A and B to be replaced with C (results in C < C), we use <code>$d A B $.</code>. A grammar with $d restrictions can be converted into an equivalent grammar with no restrictions, but it would be much longer.</p>
<p>Following statements are identified with a <strong>label token</strong>. Label tokens can contain only letters, digits, a period, a hyphen or an underscore. Labeled statements must have unique labels.</p>
<h2>Types and Hypotheses</h2>
<p>In Metamath, each word has so-called <strong>type</strong>. When a variable is substituted by a word, they both must have the same type. Types allow us to have multiple variables with the same name (but different types). A grammar with types can be converted into an equivalent grammar without types (and without type restrictions), but it would be much longer.</p>
<p>Following two kinds of statements are called <strong>hypotheses</strong>.</p>
<h3>$f statement</h3>
<pre>labelToken $f cToken vToken $.</pre>
<p><strong>Floating hypothesis</strong>. cToken must be a previously defined constant, vToken must be a previously defined variable. It is used just to define a type of variable.</p>
<h3>$e statement</h3>
<pre>labelToken $e cToken token token ... token $.</pre>
<p><strong>Essential hypothesis</strong>. cToken must be a previously defined constant.</p>
<h2>Assertions</h2>
<h3>$a statement</h3>
<pre>labelToken $a cToken token token ... token $.</pre>
<p><strong>Axiomatic assertion</strong>. cToken must be previously defined constant. It defines a word, that belongs to the language &#8220;for no reason&#8221; (like an axiom).</p>
<h3>$p statement</h3>
<pre>labelToken $p cToken token token ... token $= labelToken labelToken ... labelToken $.</pre>
<p><strong>Provable assertion</strong>. cToken must be a previously defined constant. It defines a word, that belongs to the language &#8220;with a reason&#8221;. The reason (&#8220;proof&#8221;) is a sequence of rewriting rules (between <code>$=</code> and <code>$.</code>) needed to generate the assertion word (between <code>$p</code> and <code>$=</code>).</p>
<p>Each assertion contains a word (which has or has not to be &#8220;proved&#8221;). For each assertion, there is a sequence of <strong>mandatory hypotheses</strong> related to it. These are all <code>$e</code> statements that occur before the assertion, and all <code>$f</code> statements that occur before the assertion, if their variable occurs in the assertion word (or in any of mandatory $e hypotheses). Mandatory hypotheses must be &#8220;fulfilled&#8221; before the assertion word can be fulfilled (will be clarified in description of a proof syntax).</p>
<h3>${ statement</h3>
<pre>${ statement statement ... statement $}</pre>
<p><strong>Scoping statement</strong>. These statements have a classic &#8220;bracket syntax&#8221;, they can be nested, but are usually used only to depth 1. Satements <code>$c, $v, $d, $f, $e</code> defined inside a scope become inactive after the end of a scope. Only assertions (<code>$a, $p</code>) remain active. We use them, when we want to quickly prove some statement (define new variables, disjoint restrictions, <code>$e</code> hypotehses), but we don&#8217;t want to &#8220;pollute&#8221; the environment (we don&#8217;t need these disjoint restrictions or <code>$e</code> hypotheses in the future). Non-assertion statements become forgotten, while assertions remain true even after the scope.</p>
<h2>Example</h2>
<p>Let&#8217;s write a grammar for the propositional logic</p>
<pre>
$c  wff  $.        $( we use this constant as a type of formula (well formed formula) $)
$c  ( ) ! ->  $.   $( brackets, negation, implication $)

$v  A B C  $.      $( variables to be used in formulas $)

wa  $f  wff A  $.  $( hypothesis "wa" which says, that A is a well-formed formula $)
wb  $f  wff B  $.
wc  $f  wff C  $.

$( Following assertions define the rules to create formulas $)
wng  $a wff ! A $.           $( mandatory hypotheses are (wa) $)
wim  $a wff ( A -> B ) $.    $( mandatory hypotheses are (wa, wb) $)

$c  |-  $.         $( this constant will be used as a type of provable formula  $)

$( Schemes of axioms of propositional logic $)
a1  $a |- ( A -> ( B -> A ) ) $.
a2  $a |- (    ( A -> ( B -> C ) )   ->    ( ( A -> B ) -> ( A -> C ) )    ) $.
a3  $a |- ( ( ! A -> ! B )  ->  ( B -> A ) ) $.  

$( new scope; otherwise mp1, mp2 will become mandatory for all upcoming assertions $)
${                               $( Modus Ponens rule of inference $)
    mp1 $e |- A $.                
    mp2 $e |- ( A -> B ) $.
    mp  $a |- B $.               $( mandatory hypotheses of "mp" are (wa, wb, mp1, mp2) $)
$}
</pre>
<h2>Proof syntax</h2>
<p>Proof is defined in $p statement as a sequence of labels. Labels may refer to previous labeled statements <code>$f, $e, $a, $p</code>. A sequence of labels corresponds to the generation of a proved word in <strong>Reverse Polish Notation</strong>. The substitution mechanism works as a <b>stack</b>. Operands are put on top of a stack. Operators take several operands from a stack and put a new operand (result) to the top.</p>
<p>Proof verification consists of going throug a sequence of labels and editing the stack accordingly.</p>
<p>When a hypothesis <code>$f, $e</code> occurs, we put its content as a new word on top of the stack.</p>
<pre> wa wa mp1  --->  [   wff A   ;   wff A   ;   |- A   ]</pre>
<p>When an assertion <code>$a, $p</code> occurs, it works as an operator. It takes several items form the stack, substitutes them into an assertion word, and puts a new word on top of the stack. Let&#8217;s look at the details.</p>
<p>The assertion, that we ran into, has K mandatory hypotheses. We remove K top-most items from the stack. First, we check variable types. Fist constant of each word on the stack should be equal to first constant of corresponding mandatory hypothesis. <code>$f</code> mandatory hypotheses define variables to be substituted, corresponding words on stack are values, that will replace these variables. Now we check disjoint variable restriction. Then, substitution is performed on $e hypotheses (if there are any) and compared with stack values. If values are equal, substitution is performed on assertion word, and a result is put on top of stack. Proof is valid, if at the end, there remains just a single word on the stack, which is equal to proof word.</p>
<p>Let&#8217;s prove a syntactic thing, that (A -> (B -> C)) is a formula. We take proof labels one by one and eidt a stack accordingly.</p>
<pre name="dlhl" class="js">
formula1 $p  wff ( A -> ( B -> C ) )  $= wa wb wc wim wim $.
1)  [ wff A ]
2)  [ wff A  ;  wff B ]
3)  [ wff A  ;  wff B  ;  wff C ]
4)  [ wff A  ;  wff ( B -> C ) ]   // wim has mandatory hypotheses (wa, wb). 
// their types (wff, wff) correspond with types of last two items on the stack. 
// Substitution is B for A, C for B. We substitute into wim = wff ( A -> B ) , 
// put a result  wff ( B -> C ) on stack. Note that type (first token) 
// is omitted during substitution, there is no wff ( wff B -> wff C ).
5)  [ wff ( A -> ( B -> C ) ) ]    // same thing. Types correspond. 
// We substitute A for A, ( B -> C ) for B. We have processed all labels, 
// stack word is equal to proof word, proof is correct.
</pre>
<p>Let&#8217;s prove a more interesting statement: ((A->A)->(A->A)).</p>
<pre  name="dlhl" class="js">
formula2 $p  |- ( ( A -> A ) -> ( A -> A ) )  $= wa wa wa wim wim    
                                                 wa wa wim wa wa wim  wim  
                                                 wa wa a1    
                                                 wa wa wa a2    
                                                 mp  $.
5 )  [ wff ( A -> ( A -> A ) )  ]   // processing wa wa wa wim wim

12)  [ wff ( A -> ( A -> A ) )    
       wff ( ( A -> A ) -> ( A -> A ) )  ]  // next 7 labels

15)  [ wff ( A -> ( A -> A ) )   
       wff ( ( A -> A ) -> ( A -> A ) )     
       |-  ( A -> ( A -> A ) )  ]   // next 3 labels

19)  [ wff ( A -> ( A -> A ) )  
       wff ( ( A -> A ) -> ( A -> A ) )   
       |-  ( A -> ( A -> A ) ) 
       |-  (  ( A -> ( A -> A ) )   ->   ( ( A -> A ) -> ( A -> A ) )  ) ]  // next 4

20)  [ |- ( ( A -> A ) -> ( A -> A ) )  ]  // "mp" has 4 mand. hypotheses (wa,wb,mp1,mp2) 
// with types (wff, wff, |-, |-),  which correspond to types of stack items. 
// Substitution is ( A -> ( A -> A ) ) for A, ( ( A -> A ) -> ( A -> A ) ) for B.
// We substitute into mp1, mp2, results are equal to stack item 3 and 4. We substitute  
// into mp word, result is equal to proof word, proof is correct.
</pre>
<p>Note, that <code>$p</code> assertions are used in proofs just like <code>$a</code> assertions. We use them as rewriting rules and don&#8217;t care about actual proof. Long proofs can be broken into smaller proofs of sub-theorems, e.g. for previous theorem:</p>
<pre >
th1  $p  wff ( A -> ( A -> A ) )  $=  wa wa wa wim wim  $.
th2  $p  wff ( ( A -> A ) -> ( A -> A ) )  $=  wa wa wim wa wa wim  wim  $.
th3  $p  |-  ( A -> ( A -> A ) )  $=  wa wa a1  $.
th4  $p  |-  (  ( A -> ( A -> A ) )  ->  ( ( A -> A ) -> ( A -> A ) ) )  $=  wa wa wa a2  $.
formula2 $p  |- ( ( A -> A ) -> ( A -> A ) )  $=  wa th1   wa th2   wa th3   wa th4   mp  $.
</pre>
<p><code>$a</code> assertions are used to define math syntax (recursive definition of formula), axioms of theory (a1, a2, a3) and inference rules (modus ponens), but also to define new objects and symbols, that are abbreviations of more complex statements. Let&#8217;s define disjuction $A \vee B$, which is an abbreviation for $\neg A \rightarrow B$.</p>
<pre>
$c \/  $.                          $( a constant for disjunction (\vee) $)
wor $a wff ( A \/ B )  $.          $( syntax of usage, infix notation   $)
${                                 $( one way rewrite   $)
    hy-Vee1 $e |- ( ! A -> B ) $.  
    df-Vee1 $a |- ( A \/ B ) $.
$}
${                                 $( opposite way rewrite   $)
    hy-Vee2 $e |- ( A \/ B ) $.    
    df-Vee2 $a |- ( ! A -> B ) $.
$}
</pre>
<p>Writing formal proofs requires a lot of practice. Most of the work of Metamath community is focused on developing <a href="http://us.metamath.org/mpegif/mmset.html">set.mm</a>, which is an enormous library of proofs, that starts with logic and ZF axioms and builds the rest of common mathematics. It is also available in <a href="http://mm.ivank.net" target="new">MM Tool</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/introduction-to-metamath.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Fourier Transform Clarified</title>
		<link>https://blog.ivank.net/fourier-transform-clarified.html</link>
		<comments>https://blog.ivank.net/fourier-transform-clarified.html#comments</comments>
		<pubDate>Tue, 12 Aug 2014 18:11:53 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=864</guid>
		<description><![CDATA[This article should allow you to understand Fourier transform much better. It should clarify basic principles and several important details, which are not said in other articles. It is a little informal, but all formalities should be obvious after reading it. Prerequisities Before you start to read, you must know, what is complex number, trigonometric [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>This article should allow you to understand Fourier transform much better. It should clarify basic principles and several important details, which are not said in other articles. It is a little informal, but all formalities should be obvious after reading it.</p>
<p><span id="more-864"></span></p>
<h2>Prerequisities</h2>
<p>Before you start to read, you must know, what is <a href="http://en.wikipedia.org/wiki/Complex_number">complex number</a>, trigonometric functions (sine, cosine) and <a href="http://en.wikipedia.org/wiki/Integral">integral</a>.</p>
<h2>Introduction</h2>
<p>I assume, that you have already heard about Fourier transform. It is usually shown, how the sum of sinusoids having different period creates &#8220;square&#8221; or some other function. Then cosines come out, complex numbers and deadly expression $e^i$ (you know, that $e^3 = e \cdot e \cdot e$, but what the hell is $e^i$?). In this article, we will look at things differently.</p>
<p>Imagine a wheel, which has a radius $r_0$, it has a red dot on the right side from center, it has an initial angle $\alpha_0$ and rotates with speed (angular velocity) $s_0$. This red dot draws an image of a circle.</p>
<p><img src="http://www.ivank.net/blogspot/ft/circle_1w.png" style="width:50%" /></p>
<p>Imagine, that at the red dot of that wheel, there is another wheel with a radius $r_1$, angle $\alpha_1$, that rotates with a speed $s_1$. This system of two wheels draws more interesting curve.</p>
<p><img src="http://www.ivank.net/blogspot/ft/circle_2w.png" style="width:50%" /></p>
<p>Imagine, that there may be another wheel at the dot of the last wheel, and another wheel on top of that wheel &#8230; There may be infinitely many wheels. Which curves can be drawn by such systems of wheels?</p>
<p><img src="http://www.ivank.net/blogspot/ft/circle_multi.png" style="width:50%" /></p>
<h3><strong>Theorem:</strong> We can draw any curve using a system of wheels.</h3>
<p>We can draw not only a circle, but also a square, triangle or a line. Here is a system of wheels, which draws <a href="http://www.youtube.com/watch?v=QVuU2YCwHjw">Homer Simpson</a>. We can notice, that each wheell just &#8220;adds a shift&#8221; to previous wheel. So we can interchange wheels with each other, the order of wheels is not important (because addition is commutative).</p>
<h3><strong>Theorem:</strong> If two wheels have the same speed, they can be &#8220;merged&#8221; into a single wheel (with the same speed, but different radius and angle).</h3>
<p>Let&#8217;s talk about different problem. We have a curve (continuous function $f: \mathbb{R} \rightarrow \mathbb{R}^2$), that for each parameter $t$ returns a position (x,y) &#8211; point of curve. We want to find a system of wheels, which draws that curve. System of wheels can be represented also as a function $g$, for each speed $s$ it returns a pair (r,$\alpha$) &#8211; radius and initial angle of a wheel with speed $s$ in that system (e.g. when we don&#8217;t need some wheel, $g$ gives it a radius 0). Take a deep breath and get ready for the most shocking discovery of your life. Operation, that finds a wheel system $g$ for a curve $f$, is called <strong>Fourier transform</strong>.</p>
<h2>Examples</h2>
<p>Let&#8217;s have a curve, that has a single point (0,0), i.e. $f(t) = (0,0)$. What is the Fourierova transform of it? We simply set all radii and angles to 0, i.e. $g(s) = (0,0)$.</p>
<p>Let&#8217;s have a curve, a circle, that has a radius 0.6 and center at the point (4,3), i.e. $f(t) = (4+0.6\cdot \cos(t), 3+0.6\cdot \sin(t))$. What is the Fourier transform of taht curve? We can shift the whole curve using wheel with a speed 0, we can draw a circle using some other wheel. For example:</p>
<ul>
<li>$g(0) = (5, 37.64°)$</li>
<li>$g(1) = (0.6, 0)$</li>
<li>$g(s) = (0,0)$ otherwise</li>
</ul>
<h2>Complex numbers</h2>
<p>We already know, what Fourier transform is. It looks for a function &#8220;related&#8221; to some other function. The input function works with coordinates x and y, whilst the output function works with radii and angles. It would be great to &#8220;unify&#8221; them. Moreover, the system of wheels is not unique for a curve, e.g. if we add 360° to initial angle of some wheel, it would still draw the same curve.</p>
<p>Instead of 2D coordinates for curve, let&#8217;s work with complex numbers. So instead of $(x,y)$ let&#8217;s have $(x+y\cdot i)$. Our curve is $f: \mathbb{R} \rightarrow \mathbb{C}$. That was quite easy. The second part will be slightly more complicated.</p>
<p>We have wheels at the output (pairs radius + angle). We would like to use complex numbers here too. Let that number be the initial position of red dot in a complex plane (due to the center of wheel). So, instead of $(r,\alpha)$ we have a complex number $r \cdot (\cos(\alpha)+\sin(\alpha)\cdot i) = (a + b\cdot i)$. But how do we rotate such number e.g. by 30 degrees? In our first representation, we just added a rotation to previous angle and received a new angle (radius remained the same). But how to rotate a complex number? Read carefully! <b>To rotate a complex number, one just multiplies it by another complex number.</b> Namely, $(\cos(30°) + \sin(30°)\cdot i)$. Our system of wheels also has a form $g: \mathbb{R} \rightarrow \mathbb{C}$. now</p>
<p>What is the advantage of using complex numbers instead of classic $\mathbb{R}^2$ and wheel systems? It makes everything more complicated. Complex numbers are hard to multiply and nobody likes them. It is not that easy to see wheels behind the complex numbers, but wheels are still there! We actually have few benefits. Two things (curves and wheel systems) have the form of $\mathbb{R} \rightarrow \mathbb{C}$. Also, Fourier thransform between them is <b>unique</b> &#8211; there is only one set of wheels for a curve (when both represented by complex numbers). It can be shown, that FT is injective and surjective. So there should be an <b>inverse FT</b>, that finds a curve for a system of wheels.</p>
<p>Let&#8217;s define FT once again. It is still an operation, that finds a set of wheels for parametric curve, but both things are represented by complex numbers (using functions $\mathbb{R} \rightarrow \mathbb{C}$).</p>
<p>Let&#8217;s clarify, how wheel system works, so it is clear what FT does. A red dot of the whole system should draw our curve, so for parameter $t$ red dot should be at the position $f(t)$. For $t=0$ each wheel should be at its initial position. When $t$ is increased by 1, the wheel with a speed 1 should rotate once (by $2 \pi$) and generally, a wheel with speed $s$ should rotate &#8220;$s$ times&#8221; (by $s \cdot 2 \pi$).</p>
<h2>Properties of Fourier transform</h2>
<p>Let&#8217;s say, we have a parametric curve $f$ and we have found a wheel system $g$ for it. Now we &#8220;zoom in&#8221; the curve with parameter $k$, $f_2(t) = k\cdot (x + y\cdot i)$. How would the system of wheels look like for this new curve? We just multiply a radius of each wheel by $k$! In our representation, we multiply complex numbers. So:</p>
<p>$FT(f)=g \Rightarrow FT(f_2) = k \cdot g$.</p>
<p>A little shocking detail: it works even for $k\in \mathbb{C}$ (as you can see from  <a href="http://en.wikipedia.org/wiki/De_Moivre%27s_formula">Moivre&#8217;s formula</a>).</p>
<p>Now we have curves $f_1, f_2$. Let&#8217;s create a new curve by &#8220;adding&#8221; them together, so $f_3(t) = (x_1+y_1\cdot i) + (x_2+y_2\cdot i)$. Each curve has its own system of wheels $g_1, g_2$. How does the system looks like for $f_3$? We just connect one set to the red dot of another set. We would have two wheels for each speed, and, as mentioned above, we can merge them into one wheel. How exactly does it look like? We just add complex numbers! so:</p>
<p>$FT(f_1)=g_1, FT(f_2)=g_2  \Rightarrow FT(f_3) = g_1 + g_2$.</p>
<p>These properties are often called <strong>Linearity of Fourier transform</strong>.</p>
<h2>Computing the Fourier transform</h2>
<h3>Computing inverse FT</h3>
<p>We want to know, how to transform between curves and wheel systems. First, let&#8217;s talk about inverse FT, because it is easier. We know a set of wheels $g(s)$ and we are interested in a motion of red dot &#8211; its position at parameter $t$, i.e. $f(t)$.</p>
<p>Let the system have just one wheel with non-zero radius. It has a speed $s$, radius and initial angle are represented by a complex number $g(s) = a+b\cdot i$. Where is the point of curve at $t$? We just rotate the wheel to an angle $t*s$ and compute the position of red dot. We already know how to rotate complex numbers.</p>
<p>$ f(t) =  (\cos(t\cdot  s\cdot  2 \pi) + \sin(t\cdot  s\cdot  2 \pi) i) \cdot g(s) $</p>
<p>What if we have $n$ wheels (with non-zero radii)? Each wheel has its speed $s_j$ and complex number representing radius and angle. Each wheel determines a shift from a red dot of previous wheel, so we just add these shifts.</p>
<p>$ f(t) = \sum\limits_{j=1}^n (\cos(t \cdot s_j \cdot 2 \pi) + \sin(t \cdot s_j\cdot 2 \pi) i) \cdot g(s_j) $</p>
<p>What if we have infinitely many wheels? The sum becomes an integral.</p>
<p>$ f(t) = \int\limits_{s\in\mathbb{R}} (\cos(t\cdot s\cdot 2 \pi) + \sin(t \cdot s \cdot 2 \pi) i) \cdot g(s) \mathrm{d} s$</p>
<p>Since we know, how wheels work and how to rotate complex numbers, we don&#8217;t have to remember this equation. We can &#8220;invent&#8221; it when we need it.</p>
<h3>Computing FT</h3>
<p>FT is more complicated. We have a curve $f$ a we want to find a system of wheels $g$. We want to know a complex number (radius + angle) for a wheel with a speed $s$. Here is an equation:</p>
<p>$g(s) = \int\limits_{t\in\mathbb{R}} (\cos(- t\cdot s\cdot 2 \pi) + \sin(- t \cdot s \cdot 2 \pi) i) \cdot f(t) \mathrm{d} t$</p>
<p>I don&#8217;t fully understand an idea behind that equation. You may notice, that when $s=0$, the value inside brackets is 1 and the result is an &#8220;integral over the whole curve&#8221; (= &#8220;average point&#8221;), which then corresponds to shift of the whole curve away from center.</p>
<p>When $s$ is not zero, expression inside brackets generates a circular motion, but in different direction, than IFT. The result may mean an average point, multiplied by circular motion.</p>
<h2>Fourier series</h2>
<h3><strong>Theorem:</strong> When a curve $f$ is periodic, it can be expressed by system of wheels with integer speeds.</h3>
<p>We noticed it in circle, where we needed just one wheel with a speed 1. We will need much more wheels to draw a square, but thanks to the theorem we know, that we will only need wheels having speeds 0, 1, 2, 3, &#8230; The FT for periodic curve $f$ is system of wheels $g$ in form $\mathbb{N}\rightarrow\mathbb{C}$. Inverse FT does not have to be integral, but just infinite sum (series):</p>
<p>$ f(t) = \sum\limits_{j\in\mathbb{N}} (\cos(t \cdot j \cdot 2 \pi) + \sin(t \cdot j\cdot 2 \pi) i) \cdot g(j) $</p>
<h2>Complex exponential</h2>
<p>As we have shown in an article <a href="http://blog.ivank.net/taylor-polynomial-clarified.html">about Taylor polynomial</a>, function $e^x, x \in \mathbb{R}$ has Taylor polynomial:</p>
<p>$e^x = \frac{x^0 }{ 0! } + \frac{x^1 }{ 1! } + \frac{x^2 }{ 2! }+ \frac{x^3 }{ 3! } + &#8230;$</p>
<p>Inspired by that, let&#8217;s <strong>define a complex exponentiation</strong>:</p>
<p>$e^{a+bi} = \frac{ (a+bi)^0 }{ 0! } + \frac{ (a+bi)^1 }{ 1! } + \frac{(a+bi)^2 }{ 2! }+ \frac{(a+bi)^3 }{ 3! } + &#8230;$</p>
<p>Now let&#8217;s put $ix$ into exponent:</p>
<p>$e^{ix} = \frac{{(ix)}^0}{0!} +  \frac{{(ix)}^1}{1!} + \frac{{(ix)}^2}{2!} + \frac{{(ix)}^3}{3!} + &#8230;$</p>
<p>Let&#8217;s slightly reorder summands:</p>
<p>$e^{ix} = \left(\frac{{(ix)}^0}{0!} +  \frac{{(ix)}^2}{2!} + &#8230;\right) + \left(\frac{{(ix)}^1}{1!} + \frac{{(ix)}^3}{3!} + &#8230;\right)$</p>
<p>Let&#8217;s get i in front of bracket:</p>
<p>$e^{ix} = \left(\frac{{(ix)}^0}{0!} +  \frac{{(ix)}^2}{2!} + &#8230; \right) + i\left(\frac{x^1}{1!} + \frac{i^2x^3}{3!} + &#8230;\right)$</p>
<p>$i$ is always powered to even power, so it will just multiply the number by 1 or -1:</p>
<p>$e^{ix} = \left(\frac{x^0}{0!} &#8211;  \frac{x^2}{2!} + &#8230; \right) + i\left(\frac{x^1}{1!} &#8211; \frac{x^3}{3!} + &#8230;\right)$</p>
<p>From the previous article we know, that the first bracket is Taylor series for cosine, second bracket for sine (also called <a href="http://en.wikipedia.org/wiki/Euler%27s_formula">Euler&#8217;s formula</a>):</p>
<p>$e^{ix} = \cos(x) + i \sin(x)$</p>
<p>Now we can write $e^{ix}$ everywhere instead of sines and cosines, e.g. for FT:</p>
<p>$g(s) =  \int\limits_{t\in\mathbb{R}} (\cos(- t\cdot s\cdot 2 \pi) + \sin(- t \cdot s \cdot 2 \pi) i) \cdot f(t) \mathrm{d} t =</p>
<p>\int\limits_{t\in\mathbb{R}} e^{-t\cdot s \cdot 2 \pi \cdot i} \cdot f(t) \mathrm{d} t$</p>
<p>Notice, that it is not possible to understand Euler&#8217;s formula (or FT written using Euler&#8217;s formula) without a proper knowledge of differential calculus, integrals and Taylor series.</p>
<p>There are 3 reasons to write FT with $e^{ix}$:</p>
<ul>
<li>to make equations shorter</li>
<li>to make person looks smarter</li>
<li>to make it even harder for a student to understand FT</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/fourier-transform-clarified.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Taylor polynomial clarified</title>
		<link>https://blog.ivank.net/taylor-polynomial-clarified.html</link>
		<comments>https://blog.ivank.net/taylor-polynomial-clarified.html#comments</comments>
		<pubDate>Sat, 02 Aug 2014 16:03:26 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=832</guid>
		<description><![CDATA[I decided to write this article, because all other articles I found on the internet seemed too complicated and did not explain the basic principles. I will avoid formalism, but I am sure formalisms will be clear to you after reading this article. Prerequisities Before you start to read, you must know, what is polynomial, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I decided to write this article, because all other articles I found on the internet seemed too complicated and did not explain the basic principles. I will avoid formalism, but I am sure formalisms will be clear to you after reading this article.</p>
<p><span id="more-832"></span></p>
<h2>Prerequisities</h2>
<p>Before you start to read, you must know, what is <a href="http://en.wikipedia.org/wiki/Polynomial">polynomial</a>, <a href="http://en.wikipedia.org/wiki/Derivative">derivative</a> and <a href="http://en.wikipedia.org/wiki/Factorial">factorial</a>, and be able to differentiate and integrate polynomials.</p>
<p><b>Polynomial is a function</b>, in which we put some real value <b>x</b> and receive an output value at point <b>x</b> using addition, subtraction, multiplication and division.</p>
<p><b>Derivative of a function is a number.</b> When <b>y</b> grows as fast as <b>x</b>, derivative is $=1$. When <b>y</b> grows faster than <b>x</b>, derivative is $>1$, when slower, derivative is $&lt;1$. When <b>y</b> grows, but <b>x</b> stays at the same place, derivative is $=0$.</p>
<h2>Motivation</h2>
<p>In an everyday life, one often needs to compute sine, cosine, tangent or logarithm. We don&#8217;t have to go that far. We run into problem, even when we need to compute a square root of a number. The problem is, that we (humans) know only how to add, subtract, multiply and divide. Most of us don&#8217;t know how to compute sines, logarithms or square roots. Sadly, computers can not help us. Their circuits usually can add (or add a negative value) and multiply (or multiply by inverted value) only.</p>
<p>But hundreds of yers ago, there existed mathematical tables with values of these functions. Also, when you pres SIN on your calculator, you usually receive a pretty exact answer. How do these people and machines do that?</p>
<p>The solution is in the <b>approximation</b> of our function (which we don&#8217;t know how to compute) with some different function (which we do know how to compute).</p>
<h2>Example</h2>
<p>Let&#8217;s say, we want to compute $\sin(1)$, i.e. sine of one radian, which has a value around <b>0.841470984</b>. From calculus, we can discover these 3 properties of sine:</p>
<ul>
<li>sine of zero is zero &#8230;  $\sin(0) = 0$</li>
<li>derivative of sine in zero is one &#8230; $\sin&#8217;(0) = 1$</li>
<li>sine is periodic &#8230;  $\sin(x) = \sin(x + 2\pi)$</li>
</ul>
<h2>The nice property of polynomials</h2>
<p><i><br />
<h3>&#8220;For each N points in a plane there exists a polynomial of degree at most N-1, which intersects them.&#8221;</h3>
<p></i> </p>
<p>Which means, that:</p>
<ul>
<li>for each point there is a horizontal line, which intersects it</li>
<li>for each two points there is a line, which intersects them</li>
<li>for each three points there is parabola, which intersects them</li>
<li>&#8230;</li>
</ul>
<p>It looks like polynomials can have many different shapes and &#8220;resemble&#8221; many different functions.</p>
<h2>The basic principle of Taylor polynomial</h2>
<p>Taylor polynomial is based on a simple principle:</p>
<p><i><br />
<h3>&#8220;The more similar (high order) derivatives of two functions are at point X, the more similar these functions are around point X.&#8221;</h3>
<p></i> </p>
<p>The process of reaching this idea could look like this: functions should be similar to each other (around point X). They probably should have the same value in X (obvious). They probably should enter the point X going at the same angle (we don&#8217;t want one to decrease at X and another to grow). One function should be as &#8220;curvy&#8221; as the other (we don&#8217;t want one to be convex and another to be concave). And now we may notice, that we have just mentioned derivatives of order 0, 1 and 2. It probably works like that:</p>
<ul>
<li>functions should have the same derivation of oreder 0, i.e. a function value at our point</li>
<li>when they have the same derivative of order 1 (same slope of tangent), they are more similar</li>
<li>when they have the same derivative of order 2, they are even more similar</li>
<li>&#8230;</li>
</ul>
<h2>Aapproximation with polynomials</h2>
<p>We try to approximate unknown function with polynomial, because we know how to compute it (we only add, subtract, multiply and divide).</p>
<p>Our example: $\sin(x)$ has the zeroth derivative 0 at $x=0$, first derivative 1, second derivative 0, third derivative -1 and it keeps repeating. If we find a polynomial, which has the same derivatives at $x=0$ up to some order, we can compute the value of that polynomial instead of sine and believe, that it is almost equal to sine.</p>
<h2>Example: finding polynomial for sine</h2>
<p>Let&#8217;s try to find a polynomial $p$, which is similar to sine around point zero. First, we want it to have the same derivative of order 0, then 1, 2, 3 &#8230; and gradually increase our demands. Simultaneously, let&#8217;s see, how the graph becomes more and more similar to sine, and the value at point 1, $p(1)$, gets more and more closer to $\sin(1)$.</p>
<p>The polynomial of degree 0, which has the same value at 0, as sine, is $p(x) = 0$ (same 0. derivative), p(1)= <b>0</b></p>
<ol>
<li class="spacedli">Sine has a first derivative equal to 1, it corresponds to polynomial $p(x) = x$ (same 0. and 1. derivative), p(1)= <b>1</b><br />
<br />
<img border="0" src="http://www.ivank.net/graph/newgraph.php?highquality=1&amp;zoom=50&amp;height=200&amp;width=400&amp;func0=sin(x)&amp;func1=x&amp;red1=255&amp;blue1=0&amp;green0=0" /> 
</li>
<li class="spacedli">Function $p(x) = x$ has the second derivation at 0 equal to 0, we don&#8217;t have to change it.</li>
<li class="spacedli">Third derivative of our polynomial at 0 must be -1, let&#8217;s try to integrate it and add a constant, if needed.
<ul>
<li>$p&#8221;&#8217;(x) = -1$ &#8211; at zero it should be -1 (third derivative)</li>
<li>$p&#8221;(x) = -x$ &#8211; at zero should be 0 (second derivative), which is OK</li>
<li>$p&#8217;(x) =  1 &#8211; \frac{x^2}{2}$ , at zero should be 1 (first derivative), thus + 1</li>
<li>$p(x) =  x &#8211; \frac{x^3}{6}$ at zero should be 0 (zeroth derivative), which is OK</li>
</ul>
<p>Indeed, polynomial $p(x) =  x &#8211; \frac{x^3}{6}$ is more similar to sine (same 0. to 3. derivative), p(1)= <b>0.833333</b><br />
<br />
<img border="0" src="http://www.ivank.net/graph/newgraph.php?highquality=1&amp;zoom=50&amp;height=200&amp;width=400&amp;func0=sin(x)&amp;func1=x-((x^3)/6)&amp;red1=255&amp;blue1=0&amp;green0=0" /> 
</li>
<li class="spacedli">Fourth derivative of our polynomial should be 0, but it is satisfied in previous polynomial.</li>
<li class="spacedli">Fifth derivative of our polynomial should be 1, so: 
<ul>
<li>$p&#8221;&#8221;(x) = x$ &#8211; at zero should be 0 (fourth derivative), which is OK</li>
<li>$p&#8221;&#8217;(x) =  -1 + \frac{x^2}{2}$ , at zero should be -1 (third derivative), thus &#8211; 1</li>
<li>$p&#8221;(x) =  -x + \frac{x^3}{6}$ at zero should be 0 (second derivative), which is OK</li>
<li>$p&#8217;(x) =  1 &#8211; \frac{x^2}{2} + \frac{x^4}{24} $ at zero should be 1 (first derivative), thus + 1</li>
<li>$p(x) =  x &#8211; \frac{x^3}{6}  + \frac{x^5}{120}$ at zero should be 0 (zeroth derivative), which is OK</li>
</ul>
<p>Indeed, polynomial $p(x) =  x &#8211; \frac{x^3}{6}  + \frac{x^5}{120}$ is even more similar to sine (same 0. to 5. derivative), p(1)= <b>0.841666</b><br />
<br />
<img border="0" src="http://www.ivank.net/graph/newgraph.php?highquality=1&amp;zoom=50&amp;height=200&amp;width=400&amp;func0=sin(x)&amp;func1=x-(x^3)/6plus(x^5)/120&amp;red1=255&amp;blue1=0&amp;green0=0" />
</li>
<li class="spacedli">Sixth derivative of our polynomial should be 0, but it is satisfied by previous polynomial.</li>
<li class="spacedli">In the same way, or by guessing, we can come up with the next, more precise polynomial $p(x) =  x &#8211; \frac{x^3}{6}  + \frac{x^5}{120} &#8211; \frac{x^7}{5040}$.  (same 0. to 7. derivative), p(1)= <b>0.841468</b><br />
<br />
<img border="0" src="http://www.ivank.net/graph/newgraph.php?highquality=1&amp;zoom=50&amp;height=200&amp;width=400&amp;func0=sin(x)&amp;func1=x-(x^3)/6plus(x^5)/120-(x^7)/5400&amp;red1=255&amp;blue1=0&amp;green0=0" />
</li>
</ol>
<p>We reached the function $p(x) =  x &#8211; \frac{x^3}{6}  + \frac{x^5}{120} &#8211; \frac{x^7}{5040}$, which is very similar to $\sin(x)$ around 0.</p>
<p>As you have probably noticed, $sin(x)$ has the derivatives of even order always equal to 0 at point 0. Taylor polynomial changes only when computing with precission to odd order of derivative. Now you see, where the term &#8220;odd function&#8221; came from (symmetry with respect to the origin).</p>
<h2>Taylor polynomial for any function</h2>
<p>For a general function <b>f</b> we want to find a Taylor polynomial <b>p</b>, which is very similar to <b>f</b> around some point <b>a</b>. We know several derivatives of <b>f</b> at point <b>a</b>. Polynomial <b>p</b> must have the same derivatives, as <b>f</b>, at point <b>a</b>, i. e. $p^{(i)}(a) = f^{(i)}(a)$. <b>That is our only requirement on <strong>p</strong></b>.</p>
<p>When <b>p</b> is differentiated $i$ times and we substitute <b>a</b> into it, all summands should become 0 and only the value $f^{(i)}(a)$ should remain. Thus, polynomial <b>p</b> must contain the values of these derivatives. Summands should also contain <b>(x-a)</b>, so they become 0 after substituting <b>a</b>. Summands should have a denominator, which is cancelled with exponents, which are decremented by 1 during differentiation. Denominator should be a product of these exponents, thus factorial.</p>
<h3>The following expression satisfies our requirements:</h3>
<p>$p(x) = f(a) + \frac{f&#8217;(a) * (x-a) }{ 1! } + \frac{f&#8221;(a) * (x-a)^2 }{ 2! }+ \frac{f&#8221;&#8217;(a) * (x-a)^3 }{ 3! } + &#8230;$</p>
<p>After substituting <b>a</b>, the polynomial equals $f(a)$ (other summands are 0). Let&#8217;s try to differentiate it.</p>
<p>$p&#8217;(x) = 0 + f&#8217;(a) + \frac{f&#8221;(a) * (x-a)^1 }{ 1! }+ \frac{f&#8221;&#8217;(a) * (x-a)^2 }{ 2! } + &#8230;$</p>
<p>After substituting <b>a</b>, the polynomial equals $f&#8217;(a)$ (other summands are 0). It works in the same way for higher orders of derivative.</p>
<p>Our polynomial for sine (a=0, zeroth derivative 0, first 1, second 0, third -1, fourth 0, &#8230;) is:</p>
<p>$p(x) = 0 + \frac{1 * (x-0) }{ 1! } + \frac{0 * (x-0)^2 }{ 2! }+ \frac{-1 * (x-0)^3 }{ 3! } + \frac{0* (x-0)^4 }{ 4! } + \frac{1 * (x-0)^5 }{ 5! } +&#8230; $</p>
<h2>Taylor series</h2>
<p>If we know all derivatives of some function, up to infinity, (e.g. for sine, where they repeat), we can express that function with an infinite Taylor polynomial. The value of such function can be expressed as a sum of series (infinitely many numbers).</p>
<h3>Example:</h3>
<p>For a function $y=e^x$ we know, that it has a value 1 at point 0, first and all higher derivatives are also 1. Let&#8217;s write a Taylor polynomial for this function:</p>
<p>$p(x) = 1 + \frac{1 * (x-0) }{ 1! } + \frac{1* (x-0)^2 }{ 2! }+ \frac{1* (x-0)^3 }{ 3! } + &#8230;$</p>
<p>Now we can compute the value of Euler&#8217;s number $e$ (i.e. $e^1$) up to any precission. It is:</p>
<p>$e = 1 + 1 + \frac{1}{2}+ \frac{1}{6} + \frac{1}{24} + \frac{1}{120} + &#8230;$</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/taylor-polynomial-clarified.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>3D Tool &#8211; web based 3D model viewer</title>
		<link>https://blog.ivank.net/3d-tool-web-based-3d-model-viewer.html</link>
		<comments>https://blog.ivank.net/3d-tool-web-based-3d-model-viewer.html#comments</comments>
		<pubDate>Mon, 30 Dec 2013 20:07:26 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=722</guid>
		<description><![CDATA[Let me present you 3D Tool, web-based model viewer with a simple renderer I made during this summer. It has basic functionality and can deal with several basic 3D formats. 3DTool.ivank.net. After loading 3D models, the random color is attached to each part of the model. It can be rendered using Path Tracing as a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Let me present you 3D Tool, web-based model viewer with a simple renderer I made during this summer. It has basic functionality and can deal with several basic 3D formats. <a href="http://3dtool.ivank.net">3DTool.ivank.net</a>.</p>
<p><span id="more-722"></span></p>
<p>After loading 3D models, the random color is attached to each part of the model. It can be rendered using Path Tracing as a diffuse material. The light is provided by environment map.</p>
<p>You can simply dran and drop a model into browser window, it will be parsed, HDR tree will be built (it may take a while &#8230;) and model will be added to the list. You can add environment maps (in .HDR format) in the same way.</p>
<h2>Used JS libraries</h2>
<ul>
<li> <a href="http://lib.ivank.net">IvanK.js</a> &#8211; my library for accelerated graphics in the browser </li>
<li> <a href="http://k3d.ivank.net">K3D.js</a> &#8211; my library for parsing and editing 3D meshes </li>
<li> RT.js &#8211; my library with very fast KD trees (not public) </li>
</ul>
<h2>The purpose of this project</h2>
<p>I can not see any purpose of this project right now. Some people may use it as a simple model viewer, if they don&#8217;t have any better software on their current PC (or mac, or phone, or tablet). It can be extended into a 3D model editor (but there already exist many good web-based editors) or into professional 3D renderer (but currently JS is slow, so I will wait until WebCL becomes supported in browsers).</p>
<h2>Rendered images</h2>
<p>The images below were rendered in a browser on my laptop in about 5 minutes.</p>
<p><img class="postimg" src="http://3dtool.ivank.net/promo/tree.png" /><br />
<img class="postimg" src="http://3dtool.ivank.net/promo/currant.png" /><br />
<img class="postimg" src="http://3dtool.ivank.net/promo/raptor.png" /><br />
<img class="postimg" src="http://3dtool.ivank.net/promo/t-rex.png" /></p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/3d-tool-web-based-3d-model-viewer.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Fastest Gaussian Blur (in linear time)</title>
		<link>https://blog.ivank.net/fastest-gaussian-blur.html</link>
		<comments>https://blog.ivank.net/fastest-gaussian-blur.html#comments</comments>
		<pubDate>Wed, 21 Aug 2013 22:39:22 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Math]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=662</guid>
		<description><![CDATA[I needed a really fast Gaussian blur for one of my projects. After hours of struggling and browsing the internet, I finally found the best solution. Beginning My solution is based on Fast image convolutions by Wojciech Jarosz. Presented ideas are very simple and I don&#8217;t know who is the original author. I am going [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I needed a really fast Gaussian blur for one of my projects. After hours of struggling and browsing the internet, I finally found the best solution.</p>
<p><span id="more-662"></span></p>
<h2>Beginning</h2>
<p>My solution is based on <a href="//elynxsdk.free.fr/ext-docs/Blur/Fast_box_blur.pdf">Fast image convolutions</a> by Wojciech Jarosz.<br />
Presented ideas are very simple and I don&#8217;t know who is the original author. I am going to describe it a little better and add some mathematics.<br />
To get motivated, take a glance at <a href="#results">the results</a>. I have implemented this code into <a href="//www.photopea.com">Photopea</a> under Filter &#8211; Blur &#8211; Gaussian Blur.
</p>
<h2>Definition</h2>
<p>The <a href="//en.wikipedia.org/wiki/Convolution">convolution</a> of two 2D functions $f$ and $g$ is defined as the volume of product of $f$ and &#8220;shifted&#8221; $g$. The second function $g$ is sometimes called &#8220;weight&#8221;, since it determines, how much of $f$ will get into the result</p>
<p>The Gaussian blur of a 2D function can be defined as a convolution of that function with 2D <a href="//en.wikipedia.org/wiki/Gaussian_function">Gaussian function</a>. Our gaussian function has an integral 1 (volume under surface) and is uniquely defined by one parameter $\sigma$ called standard deviation. We will also call it &#8220;radius&#8221; in the text below.</p>
<p>In our discrete finite case, we represent our 2D functions as matrices of values. We compute the volume (integral) as a sum. Gaussian function has near to zero values behind some radius, so we will use only the values  $-r \leq x \leq r, -r \leq y \leq r$. This &#8220;useful&#8221; part of weight is also called the <strong>kernel</strong>.The value of convolution at [i, j] is the weighted average, i. e. sum of function values around [i, j] multiplied by weight.</p>
<h2>Algorithm 1</h2>
<p>For a general discrete convolution of $f$ and weight function $w$, we can compute the result $b$ as:</p>
<p><big><br />
$b[i,j] = \sum\limits_{y=i-r}^{i+r}  \sum\limits_{x=j-r}^{j+r} f[y,x] * w[y,x]$<br />
</big></p>
<p>For gaussian weight, we can compute only weights around [i, j] (area of $4 \cdot r^2$). When our matrix has $n$ values, the time complexity is $O(n \cdot r^2)$. For large radii, e. g. $r = 10$, we have to do $n * 400$ operations, which correspond to 400 loops over the whole matrix and that is ugly.</p>
<pre name="dlhl" class="js">
// source channel, target channel, width, height, radius
function gaussBlur_1 (scl, tcl, w, h, r) {
    var rs = Math.ceil(r * 2.57);     // significant radius
    for(var i=0; i&lt;h; i++)
        for(var j=0; j&lt;w; j++) {
            var val = 0, wsum = 0;
            for(var iy = i-rs; iy&lt;i+rs+1; iy++)
                for(var ix = j-rs; ix&lt;j+rs+1; ix++) {
                    var x = Math.min(w-1, Math.max(0, ix));
                    var y = Math.min(h-1, Math.max(0, iy));
                    var dsq = (ix-j)*(ix-j)+(iy-i)*(iy-i);
                    var wght = Math.exp( -dsq / (2*r*r) ) / (Math.PI*2*r*r);
                    val += scl[y*w+x] * wght;  wsum += wght;
                }
            tcl[i*w+j] = Math.round(val/wsum);            
        }
}</pre>
<h2>Algorithm 2</h2>
<p>Let&#8217;s introduce the <b>box blur</b>. It is the convolution of function $f$ and weight $w$, but weight is constant and lies within a square (box). The nice property of the box blur is, that several passes (convolutions) with a box blur approximate one pass with a gaussian blur. </p>
<p>In this algorithm, we will simulate the gaussian blur with 3 passes of box blur. Let&#8217;s denote the half of size of square as $br$ (&#8220;box radius&#8221;). The constant value of weight is $1 / (2 \cdot br)^2$ (so the sum over the whole weight is 1). We can define box blur as:</p>
<p><big><br />
$bb[i,j] = \sum\limits_{y=i-br}^{i+br}  \sum\limits_{x=j-br}^{j+br} f[y,x]  / (2 \cdot br)^2 $<br />
</big></p>
<p>We have to convert the standard deviation of gaussian blur $r$ into dimensions of boxes for box blur. I am not very good at calculus, but fortunatelly I have found <a href="//www.csse.uwa.edu.au/~pk/research/matlabfns/#integral">this website</a> and used their implementation.</p>
<pre name="dlhl" class="js">
function boxesForGauss(sigma, n)  // standard deviation, number of boxes
{
    var wIdeal = Math.sqrt((12*sigma*sigma/n)+1);  // Ideal averaging filter width 
    var wl = Math.floor(wIdeal);  if(wl%2==0) wl--;
    var wu = wl+2;
				
    var mIdeal = (12*sigma*sigma - n*wl*wl - 4*n*wl - 3*n)/(-4*wl - 4);
    var m = Math.round(mIdeal);
    // var sigmaActual = Math.sqrt( (m*wl*wl + (n-m)*wu*wu - n)/12 );
				
    var sizes = [];  for(var i=0; i&lt;n; i++) sizes.push(i&lt;m?wl:wu);
    return sizes;
}</pre>
<p>Our algorithm has still the same complexity $O(n \cdot r^2)$, but it has two advantages: first, the area is much smaller ($br$ is almost equal to $\sigma$, while significant radius for gaussian is much larger). The second advantage is, that the weight is constant. Even though we have to do it 3 times, it performs faster.</p>
<pre name="dlhl" class="js">
function gaussBlur_2 (scl, tcl, w, h, r) {
    var bxs = boxesForGauss(r, 3);
    boxBlur_2 (scl, tcl, w, h, (bxs[0]-1)/2);
    boxBlur_2 (tcl, scl, w, h, (bxs[1]-1)/2);
    boxBlur_2 (scl, tcl, w, h, (bxs[2]-1)/2);
}
function boxBlur_2 (scl, tcl, w, h, r) {
    for(var i=0; i&lt;h; i++)
        for(var j=0; j&lt;w; j++) {
            var val = 0;
            for(var iy=i-r; iy&lt;i+r+1; iy++)
                for(var ix=j-r; ix&lt;j+r+1; ix++) {
                    var x = Math.min(w-1, Math.max(0, ix));
                    var y = Math.min(h-1, Math.max(0, iy));
                    val += scl[y*w+x];
                }
            tcl[i*w+j] = val/((r+r+1)*(r+r+1));
        }
}</pre>
<h2>Algorithm 3</h2>
<p>We have already simplified gaussian blur into 3 passes of box blur. Let&#8217;s do a little experiment. Let&#8217;s define a <strong>horizontal blur</strong> and <strong>total blur</strong>:</p>
<p><big><br />
$ b_h[i,j] =   \sum\limits_{x=j-br}^{j+br} f[i,x]  / (2 \cdot br)   \\<br />
   b_t[i,j] =   \sum\limits_{y=j-br}^{j+br} b_h[y,j]  / (2 \cdot br) $<br />
</big></p>
<p>Those two functions are &#8220;looping&#8221; in a line, producing &#8220;one-dimensional blur&#8221;. Let&#8217;s see, what total blur corresponds to:</p>
<p><big><br />
$b_t[i,j] =   \sum\limits_{y=i-br}^{i+br} b_h[y,j]  / (2 \cdot br)<br />
            =   \sum\limits_{y=j-br}^{j+br} \left(   \sum\limits_{x=j-br}^{j+br} f[y,x]  / (2 \cdot br)   \right)  / (2 \cdot br) \\<br />
            =   \sum\limits_{y=i-br}^{i+br}  \sum\limits_{x=j-br}^{j+br} f[y,x]  / (2 \cdot br)^2  $<br />
</big></p>
<p>We just discovered, that our total blur is a box blur! Both total blur and horizontal blur have a complexity $O(n \cdot r)$, so the whole box blur has $O(n \cdot r)$.</p>
<pre name="dlhl" class="js">
function gaussBlur_3 (scl, tcl, w, h, r) {
    var bxs = boxesForGauss(r, 3);
    boxBlur_3 (scl, tcl, w, h, (bxs[0]-1)/2);
    boxBlur_3 (tcl, scl, w, h, (bxs[1]-1)/2);
    boxBlur_3 (scl, tcl, w, h, (bxs[2]-1)/2);
}
function boxBlur_3 (scl, tcl, w, h, r) {
    for(var i=0; i&lt;scl.length; i++) tcl[i] = scl[i];
    boxBlurH_3(tcl, scl, w, h, r);
    boxBlurT_3(scl, tcl, w, h, r);
}
function boxBlurH_3 (scl, tcl, w, h, r) {
    for(var i=0; i&lt;h; i++)
        for(var j=0; j&lt;w; j++)  {
            var val = 0;
            for(var ix=j-r; ix&lt;j+r+1; ix++) {
                var x = Math.min(w-1, Math.max(0, ix));
                val += scl[i*w+x];
            }
            tcl[i*w+j] = val/(r+r+1);
        }
}   
function boxBlurT_3 (scl, tcl, w, h, r) {
    for(var i=0; i&lt;h; i++)
        for(var j=0; j&lt;w; j++) {
            var val = 0;
            for(var iy=i-r; iy&lt;i+r+1; iy++) {
                var y = Math.min(h-1, Math.max(0, iy));
                val += scl[y*w+j];
            }
            tcl[i*w+j] = val/(r+r+1);
        }
}</pre>
<h2>Algorithm 4</h2>
<p>One-dimensional blur can be computed even faster. E. g. we want to compute horizontal blur. We compute $b_h[i,j], b_h[i,j+1], b_h[i,j+2], &#8230;$. But the neighboring values $b_h[i,j]$ and $b_h[i,j+1]$ are almost the same. The only difference is in one left-most value and one right-most value. So<br />
$b_h[i,j+1] = b_h[i,j] + f[i,j+r+1] &#8211; f[i,j-r]$.
</p>
<p>In our new algorithm, we will compute the one-dimensional blur by creating the <strong>accumulator</strong>. First, we put the value of left-most cell into it. Then we will compute next values just by editing the previous value in constant time. This 1D blur has the complexity $O(n)$ (independent on $r$). But it is performed twice to get box blur, which is performed 3 times to get gaussian blur. So the complexity of this gaussian blur is 6 * $O(n)$.</p>
<pre name="dlhl" class="js">
function gaussBlur_4 (scl, tcl, w, h, r) {
    var bxs = boxesForGauss(r, 3);
    boxBlur_4 (scl, tcl, w, h, (bxs[0]-1)/2);
    boxBlur_4 (tcl, scl, w, h, (bxs[1]-1)/2);
    boxBlur_4 (scl, tcl, w, h, (bxs[2]-1)/2);
}
function boxBlur_4 (scl, tcl, w, h, r) {
    for(var i=0; i&lt;scl.length; i++) tcl[i] = scl[i];
    boxBlurH_4(tcl, scl, w, h, r);
    boxBlurT_4(scl, tcl, w, h, r);
}
function boxBlurH_4 (scl, tcl, w, h, r) {
    var iarr = 1 / (r+r+1);
    for(var i=0; i&lt;h; i++) {
        var ti = i*w, li = ti, ri = ti+r;
        var fv = scl[ti], lv = scl[ti+w-1], val = (r+1)*fv;
        for(var j=0; j&lt;r; j++) val += scl[ti+j];
        for(var j=0  ; j&lt;=r ; j++) { val += scl[ri++] - fv       ;   tcl[ti++] = Math.round(val*iarr); }
        for(var j=r+1; j&lt;w-r; j++) { val += scl[ri++] - scl[li++];   tcl[ti++] = Math.round(val*iarr); }
        for(var j=w-r; j&lt;w  ; j++) { val += lv        - scl[li++];   tcl[ti++] = Math.round(val*iarr); }
    }
}
function boxBlurT_4 (scl, tcl, w, h, r) {
    var iarr = 1 / (r+r+1);
    for(var i=0; i&lt;w; i++) {
        var ti = i, li = ti, ri = ti+r*w;
        var fv = scl[ti], lv = scl[ti+w*(h-1)], val = (r+1)*fv;
        for(var j=0; j&lt;r; j++) val += scl[ti+j*w];
        for(var j=0  ; j&lt;=r ; j++) { val += scl[ri] - fv     ;  tcl[ti] = Math.round(val*iarr);  ri+=w; ti+=w; }
        for(var j=r+1; j&lt;h-r; j++) { val += scl[ri] - scl[li];  tcl[ti] = Math.round(val*iarr);  li+=w; ri+=w; ti+=w; }
        for(var j=h-r; j&lt;h  ; j++) { val += lv      - scl[li];  tcl[ti] = Math.round(val*iarr);  li+=w; ti+=w; }
    }
}</pre>
<p><a name="results"></a><br />
<h2>Results</h2>
<p>I was testing all 4 algorithms on an image below (4 channels, 800&#215;200 pixels). Here are the results:</p>
<table>
<tr>
<th>Algorithm</th>
<th>Time, r=5</th>
<th>Time, r=10</th>
<th>Time complexity</th>
</tr>
<tr>
<td>Algorithm 1</td>
<td>7 077 ms</td>
<td>27 021 ms</td>
<td>$O(n \cdot r^2)$</td>
</tr>
<tr>
<td>Algorithm 1 (pre-computed weight)</td>
<td>2 452 ms</td>
<td>8 990 ms</td>
<td>$O(n \cdot r^2)$</td>
</tr>
<tr>
<td>Algorithm 2</td>
<td>586 ms</td>
<td>2 437 ms</td>
<td>$O(n \cdot r^2)$</td>
</tr>
<tr>
<td>Algorithm 3</td>
<td>230 ms</td>
<td>435 ms</td>
<td>$O(n \cdot r)$</td>
</tr>
<tr>
<td>Algorithm 4</td>
<td>32 ms</td>
<td>34 ms</td>
<td>$O(n)$</td>
</tr>
</table>
<p>Note, that Alg 1 is computing the true Gaussian blur using gaussian kernel, while Alg 2,3,4 are only approximating it with 3 passes of box blur. The difference between Alg 2,3,4 is in complexity of computing box blur, their outputs are the same.</p>
<p><strong>Original image</strong></p>
<p><img src="//www.ivank.net/blogspot/blur/cballs.png" class="postimg" /></p>
<p><strong>Perfect Gaussian Blur (Algorithm 1)</strong></p>
<p><img src="//www.ivank.net/blogspot/blur/cballs_a1_5.png" class="postimg" /></p>
<p><strong>Algorithm 2, 3, 4</strong>, average error per pixel: 0.04 %</p>
<p><img src="//www.ivank.net/blogspot/blur/cballs_a4_5.png" class="postimg" /></p>
<p><strong>Blur by Adobe Photoshop</strong>, average error per pixel: 0.09%</p>
<p><img src="//www.ivank.net/blogspot/blur/cballs_ps_5.png" class="postimg" /></p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/fastest-gaussian-blur.html/feed</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>SmallPT in Javascript</title>
		<link>https://blog.ivank.net/smallpt-in-javascript.html</link>
		<comments>https://blog.ivank.net/smallpt-in-javascript.html#comments</comments>
		<pubDate>Fri, 15 Feb 2013 17:36:41 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[smallpt]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=642</guid>
		<description><![CDATA[I recently found a very interesting project, called SmallPT. It is photorealistic 3D renderer, written in 99 lines. So I decided to rewrite it into JavaScript. SmallPT SmallPT is a photorealistic renderer. It uses Monte Carlo path tracing to render the scene. It contains 3 materials: diffuse material, mirror and glass, and one primitive: sphere. [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I recently found a very interesting project, called <a href="http://www.kevinbeason.com/smallpt/">SmallPT</a>. It is photorealistic 3D renderer, written in 99 lines. So I decided to rewrite it into JavaScript.</p>
<p><span id="more-642"></span></p>
<h2>SmallPT</h2>
<p>SmallPT is a photorealistic renderer. It uses Monte Carlo path tracing to render the scene. It contains 3 materials: diffuse material, mirror and glass, and one primitive: sphere. For more info, read the <a href="http://www.kevinbeason.com/smallpt/">official Kevin Beason&#8217;s webpage</a>.</p>
<p>Rewriting C++ to JS was pretty simple. I just had to remove type identifiers (&#8220;var&#8221; instead of &#8220;int&#8221;, &#8220;double&#8221;, &#8220;Vec&#8221;, &#8230;). I also had to rewrite classes into JS constructors. In Javascript, you can not overload operators, so I had to rewrite all expressions with vector operations into function calls.</p>
<h2>Try it yourself</h2>
<p>Below is the official 99-line JS version of SmallPT. You can pass it 3 comma-separated parameters: width, height and number of iterations. E.g.<br />
<code>smallpt.html#800,600,4</code><br />
will produce a 800&#215;600 image with 4 iterations of algorithm (more iterations = better image).</p>
<p>I also have written another version with explicit light sampling, also from Kevin Beason. I added several scenes and a simple UI with continuous updating of bitmap.</p>
<ul>
<li><a target="_new" href="http://renderer.ivank.net/smallpt.html#128,96,8">Official 99-line Javascript version of SmallPT</a></li>
<li><a target="_new" href="http://renderer.ivank.net">Interactive version of SmallPT</a></li>
<li>Rendered images: <a target="_new" href="http://renderer.ivank.net/balls.jpg">Color Balls</a>, <a target="_new" href="http://renderer.ivank.net/cornell.jpg">Cornel Box</a>,</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/smallpt-in-javascript.html/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Pathtraced online game</title>
		<link>https://blog.ivank.net/pathtraced-online-game.html</link>
		<comments>https://blog.ivank.net/pathtraced-online-game.html#comments</comments>
		<pubDate>Fri, 18 Jan 2013 02:57:29 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[game]]></category>
		<category><![CDATA[glsl]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[path tracing]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=632</guid>
		<description><![CDATA[I have made a Raytraced Online Game few months ago. It looks nice, but it does not look realistic, so I decided to rewrite it into Path Tracing. Scene The scene geometry is the same, as in raytraced version, with one difference &#8211; I made bigger sun. All materials are perfectly diffuse. There is a [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>
I have made a <a href="http://blog.ivank.net/first-raytraced-online-game.html">Raytraced Online Game</a> few months ago. It looks nice, but it does not look realistic, so I decided to rewrite it into <a href="http://en.wikipedia.org/wiki/Path_tracing">Path Tracing</a>.
</p>
<p><span id="more-632"></span></p>
<h2>Scene</h2>
<p>
The scene geometry is the same, as in raytraced version, with one difference &#8211; I made bigger sun. All materials are perfectly diffuse. There is a simple environment map with different color gradients on each hemisphere.
</p>
<h2>Algorithm</h2>
<p>
I have implemented the most primitive Pathtracing method. Rays are traced through the scene with cosine-importance-sampled random reflection direction. Path has non-zero color, when it hits the sun or environment map. Path is &#8220;killed&#8221; by russian roulette.
</p>
<p>
There is one thing I am worried about. I couldn&#8217;t make any propper random number generator in GLSL. It seems, that my current generator is not totally random, so resulting image is a little biased (there appear color artifacts on balls after some time of rendering).
</p>
<p>So, here it is:</p>
<ul>
<li><a href="http://pog.ivank.net">Pathtraced online game</a></li>
<li><a href="https://plus.google.com/photos/100474008784367861216/albums/5836054831022576097">Screenshots</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/pathtraced-online-game.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Interpolation with Cubic Splines</title>
		<link>https://blog.ivank.net/interpolation-with-cubic-splines.html</link>
		<comments>https://blog.ivank.net/interpolation-with-cubic-splines.html#comments</comments>
		<pubDate>Wed, 21 Nov 2012 21:23:14 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Math]]></category>
		<category><![CDATA[cubic spline]]></category>
		<category><![CDATA[interpolation]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=611</guid>
		<description><![CDATA[Adobe Photoshop, Gimp and many other image editors have a tool called Curves. There are several &#8220;knots&#8221; and while you move them, it computes a curve in between. I always wondered, how is this curve computed. About cubic splines First, I must say, that we are going to interpolate a function of one real variable, [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>
Adobe Photoshop, Gimp and many other image editors have a tool called Curves. There are several &#8220;knots&#8221; and while you move them, it computes a curve in between. I always wondered, how is this curve computed.
</p>
<p><span id="more-611"></span></p>
<p><iframe height="440" src="//www.ivank.net/blogspot/cspline/" style="border: 5px solid #282923;" width="650"></iframe></p>
<h2>About cubic splines</h2>
<p>
First, I must say, that we are going to interpolate a function of one real variable, not a curve in a 2D space.
</p>
<p>
Having several ($n$) &#8220;knots&#8221; &#8211; points in 2D space &#8211; pairs $(x, f(x))$, we would like to interpolate between them with a smooth curve. We can interpolate between them with a polynomial of the degree $n-1$, but it usually generates a curve, which is too &#8220;wavy&#8221;. The idea with splines is, that we compute a unique polynomial for each sub-interval between knots, and these polynomials should look good together &#8211; they should have the same first, second, third &#8230; derivatives at knots.
</p>
<p>I recommend you to read about <a href="http://en.wikipedia.org/wiki/Spline_(mathematics)">Splines on Wikipedia.</a>.</p>
<p>The algorithm for cubic interpolation is also described <a href="http://en.wikipedia.org/wiki/Spline_interpolation#Algorithm_to_find_the_interpolating_cubic_spline">on Wikipedia</a>, so I just copied it.</p>
<h2>Implementation</h2>
<p>
In acubic splines interpolation, the input is the set of knots + first derivatives for each knot. I decided to represent it with three arrays: an array of X values (xs), an array of Y values (ys) and an array of derivative values (ks). Here is the function for evaluating a cubic spline for any point X:
</p>
<pre name="dlhl" class="js">
CSPL.evalSpline = function(x, xs, ys, ks)
{
    var i = 1;
    while(xs[i]&lt;x) i++;
		
    var t = (x - xs[i-1]) / (xs[i] - xs[i-1]);
		
    var a =  ks[i-1]*(xs[i]-xs[i-1]) - (ys[i]-ys[i-1]);
    var b = -ks[i  ]*(xs[i]-xs[i-1]) + (ys[i]-ys[i-1]);
		
    var q = (1-t)*ys[i-1] + t*ys[i] + t*(1-t)*(a*(1-t)+b*t);
    return q;
}</pre>
<p>
In a code above, we can give the function any first derivatives (ks). But we usually don&#8217;t have any specific derivatives, we just want the curve to be as smooth as possible.</p>
<p>From the spline definition, the first and the second derivative of a cubic spline should be continuous. Below is the function, which generates the array of &#8220;ks&#8221;, which have that property. It also sets the second derivative of the first and the last point to zero (Natural Spline).
</p>
<pre name="dlhl" class="js">
CSPL.getNaturalKs = function(xs, ys, ks)    // in x values, in y values, out k values
{
    var n = xs.length-1;
    var A = CSPL._gaussJ.zerosMat(n+1, n+2);
        
    for(var i=1; i&lt;n; i++)    // rows
    {
        A[i][i-1] = 1/(xs[i] - xs[i-1]);
        
        A[i][i  ] = 2 * (1/(xs[i] - xs[i-1]) + 1/(xs[i+1] - xs[i])) ;
        
        A[i][i+1] = 1/(xs[i+1] - xs[i]);
        
        A[i][n+1] = 3*   ( (ys[i]-ys[i-1])/ ((xs[i] - xs[i-1])*(xs[i] - xs[i-1])) 
                         +  (ys[i+1]-ys[i])/ ((xs[i+1] - xs[i])*(xs[i+1] - xs[i])) );
    }
    
    A[0][0  ] = 2/(xs[1] - xs[0]);
    A[0][1  ] = 1/(xs[1] - xs[0]);
    A[0][n+1] = 3 * (ys[1] - ys[0]) / ((xs[1]-xs[0])*(xs[1]-xs[0]));
    
    A[n][n-1] = 1/(xs[n] - xs[n-1]);
    A[n][n  ] = 2/(xs[n] - xs[n-1]);
    A[n][n+1] = 3 * (ys[n] - ys[n-1]) / ((xs[n]-xs[n-1])*(xs[n]-xs[n-1]));
        
    CSPL._gaussJ.solve(A, ks);        
}</pre>
<p>Where A is $n \times (n+1)$ matrix and <i>CSPL._gaussJ.solve</i> solves the system of linear equations.</p>
<p>I put all my spline code into a small Javascript library named CSPL, which you can find here: <a href="https://github.com/kuckir/CSPL.js">CSPL &#8211; small Javascript library for cubic spline interpolation</a>.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/interpolation-with-cubic-splines.html/feed</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
		<item>
		<title>Floyd-Steinberg dithering in JavaScript</title>
		<link>https://blog.ivank.net/floyd-steinberg-dithering-in-javascript.html</link>
		<comments>https://blog.ivank.net/floyd-steinberg-dithering-in-javascript.html#comments</comments>
		<pubDate>Sat, 25 Aug 2012 20:33:40 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[dithering]]></category>
		<category><![CDATA[error difussion]]></category>
		<category><![CDATA[floyd-steinberg]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=587</guid>
		<description><![CDATA[There are many &#8220;smart&#8221; algorithms in 2D graphics and Floyd-Steinberg error diffusion is one of them. Attached demo demonstrates a dithering on webcam output (or Bucks Bunny video, when webcam is not available). Open demo in a new window What is the problem The problem is, that we have an image (table of pixels) in [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>There are many &#8220;smart&#8221; algorithms in 2D graphics and Floyd-Steinberg error diffusion is one of them. Attached demo demonstrates a dithering on webcam output (or Bucks Bunny video, when webcam is not available).</p>
<p><span id="more-587"></span><br />
<iframe height="500" src="//www.ivank.net/blogspot/dithering/dithering.html" style="border: 5px solid #282923;" width="650" allow="camera;microphone"></iframe><br />
<br/><a href="//www.ivank.net/blogspot/dithering/dithering.html" target="_new"><br />
Open demo in a new window</a></p>
<h2>What is the problem</h2>
<p>
The problem is, that we have an image (table of pixels) in format, which uses lots of colors (hundreds, thousands, millions &#8230;) and we want to display it with less colors, and we already have both palettes. There might be many reasons for doing that.
</p>
<ol>
<li>Compression: instead of 24 bits for pixel we can use only 16, 8, 2 or even 1 bit per pixel. E.g. GIF format uses 8 bits per pixel.</li>
<li>Displaying it on displays, which don&#8217;t have many colors (e-book readers, LED boards, &#8230;)</li>
<li>Printing an image on some special printers or plotters.</li>
<li>Embroiding an image on cloth using cross-stich.</li>
</ol>
<h2>What is the solution</h2>
<p>
The obvious solution is to round the color values from big palette to the &#8220;closest&#8221; values in the small palette. Let&#8217;s say we have a grayscale image with 100 possible pixel values (1, 2, &#8230; 100) and we want to &#8220;express&#8221; it using only 2 values (1 or 100). When we have an area in our image, where all the pixels have value 40 (let&#8217;s call it 40v), we round it and we get 0v. When it is 70v, we round it and we get 100v.
</p>
<p>
Dithering is a little different attitude. When we draw that 40v area, we want to draw 0v pixels and sometimes 100v pixels between them, so the whole area looks like 40v.
</p>
<p>
One way of doing dithering is error distribution. Now we also round the pixel values, but when we are making a pixel darker (40v to 0v), we also say the neighbouring pixels to be a little lighter. An &#8220;error&#8221; is a difference between real (input) color and rounded (output) color and we somehow &#8220;split&#8221; that difference to neighbours. Neighbours can split their errors to their neighbours, sometimes the errors accumulate and a pixel becomes 100v.
</p>
<h3>Floyd-Steinberg algorithm</h3>
<p>
Floyd-Steinberg algorithm says, that we should add 7/16 of error to the right neighbour, 3/16 to the bottom left, 5/16 to bottom and 1/16 to bottom right neithbour. You can read more about it in <a href="http://en.wikipedia.org/wiki/Floyd-Steinberg">Wikipedia article about Floyd-Steinberg</a>.
</p>
<h2>JavaScript implementation</h2>
<pre name="dlhl" class="js">
// byte shift by 4 (x = x&gt;&gt;4;) corresponds to integer division by 16

/*
   function converts values from grayscale (0-255) to black and white (0 or 255)
*/

function floydSteinberg(sb, w, h)   // source buffer, width, height
{
   for(var i=0; i&lt;h; i++)
      for(var j=0; j&lt;w; j++)
      {
         var ci = i*w+j;               // current buffer index
         var cc = sb[ci];              // current color
         var rc = (cc&lt;128?0:255);      // real (rounded) color
         var err = cc-rc;              // error amount
         sb[ci] = rc;                  // saving real color
         if(j+1&lt;w) sb[ci  +1] += (err*7)&gt;&gt;4;  // if right neighbour exists
         if(i+1==h) continue;   // if we are in the last line
         if(j  &gt;0) sb[ci+w-1] += (err*3)&gt;&gt;4;  // bottom left neighbour
                   sb[ci+w  ] += (err*5)&gt;&gt;4;  // bottom neighbour
         if(j+1&lt;w) sb[ci+w+1] += (err*1)&gt;&gt;4;  // bottom right neighbour
      }
}
</pre>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/floyd-steinberg-dithering-in-javascript.html/feed</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>First raytraced online game</title>
		<link>https://blog.ivank.net/first-raytraced-online-game.html</link>
		<comments>https://blog.ivank.net/first-raytraced-online-game.html#comments</comments>
		<pubDate>Fri, 25 May 2012 23:43:49 +0000</pubDate>
		<dc:creator><![CDATA[Ivan Kuckir]]></dc:creator>
				<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=577</guid>
		<description><![CDATA[I had some free time last weekend, so I decided to try to write some simple raytracer. It runs in real time on the GPU, it is controlled by JavaScript. Inspiration The first time when I heard about raytracing was about 3 years ago. I was fascinated, though, I had absolutely no idea how it [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>I had some free time last weekend, so I decided to try to write some simple raytracer. It runs in real time on the GPU, it is controlled by JavaScript.</p>
<p><span id="more-577"></span></p>
<h2>Inspiration</h2>
<p>The first time when I heard about raytracing was about 3 years ago. I was fascinated, though, I had absolutely no idea how it works. It seemd to me like some kind of magic.</p>
<p>I was attending 2 courses of computer graphics and a course about hardware and rasterization during the past year, so now I know a little bit of this magic <img src="https://blog.ivank.net/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" />  .I decided to write my own simple raytracer from the scratch.</p>
<p>I have seen several raytracers that run on CPU, some of them were even in JavaScript. I also have seen some raytracers that run on GPU, written in shading languages. I wanted to make a real-time raytracer that shows the animation, but to make it more interesting, I made a simple game from it <img src="https://blog.ivank.net/wp-includes/images/smilies/icon_smile.gif" alt=":)" class="wp-smiley" />  .</p>
<p><big><a href="http://frog.ivank.net">First Raytraced Online Game</a></big></p>
<h3>Description</h3>
<p>There is a rectangular floor and two balls on it. When you click &#8220;Start&#8221;, balls start to move and try to roll over you. You have to run away using cursor keys (or jump over the ball using spacebar).</p>
<h2>Technology</h2>
<p>The drawing is coded in GLSL, in fragment shader. Game logic is written in JavaScript, passed to the GPU using &#8220;uniforms&#8221;. The whole thing can run in web browser using WebGL technology.</p>
<p>There is a static texture of outer environment. Balls and floor are shaded using <a href="http://en.wikipedia.org/wiki/Phong_shading">Phong model</a>.<br />
There are two levels of ray &#8220;recursion&#8221; (just two calls of function, recursive functions are not allowed in GLSL).
</p>
<h3>Conclusion</h3>
<p>I have an average 3 years old laptop and Windows OS. I could run the demo at 60 FPS at Medium size and 43 FPS at Large size.</p>
<p>I really wanted to add much more interesting objects and effects into the game. But unfortunatelly, it was starting to be really slow (30 and less FPS). There are some new technologies &#8211; OpenCL or CUDA &#8211; which allow us to use GPU more efficiently than through shaders. There even is a new standard called <a href="http://www.khronos.org/webcl/">WebCL</a>, but sadly, currently it is not implemented in any official release of any browser.</p>
]]></content:encoded>
			<wfw:commentRss>https://blog.ivank.net/first-raytraced-online-game.html/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
