tag:blogger.com,1999:blog-17988836763840764862024-03-05T12:24:01.590-08:00MetalightShedding 'light' on various things, mainly (my) religion, Lisp programming and mathematics.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.comBlogger37125tag:blogger.com,1999:blog-1798883676384076486.post-2392189459043988112014-01-28T03:53:00.002-08:002014-01-28T19:06:08.017-08:00Archively: Delayed Archive/Delete in GmailEver wanted some emails to go away on their own? It might be an "I'm away for two weeks" email, and you don't want to delete the email right now or you'll forget that they're not contactable. Or do you get emails like "Fridge is being cleaned this Friday"? Well, now you can set them to be deleted or archived (or both!) when you want them to be. Enter Archively, a Google Apps Script written in JavaScript.<br />
<br />
What Archively does is scan for labels that instruct it to archive and/or delete emails. There are two top level labels, namely, "delete" and "arkive" (the label "archive" is reserved by Gmail). To archive, the label should be nested under "arkive", with a name like "in 5 days". To the Google Apps Script, the label will look like "arkive/in 5 days". Here are some examples of labels that are understood by Archively:<br />
<ul>
<li><span style="background-color: lime;"><span style="font-family: "Courier New",Courier,monospace;">arkive/at EOD</span></span> this will archive the message/thread just after midnight (at End Of Day).</li>
<li><span style="font-family: "Courier New",Courier,monospace;"><span style="background-color: lime;">arkive/at EOD+1d</span></span> this will archive the message/thread after midnight the following day (at End Of Day plus one more day).</li>
<li><span style="background-color: lime;"><span style="font-family: "Courier New",Courier,monospace;">arkive/when 7wks old</span></span> will archive the message/thread when the last message in the thread is 7 weeks old. If any new messages arrive (in this thread), it will have to wait till the latest message is 7 weeks old.</li>
<li><span style="background-color: cyan;"><span style="font-family: "Courier New",Courier,monospace;">delete/in 2 weeks</span></span> will delete the message/thread two weeks after the label is spotted.</li>
<li><span style="background-color: cyan;"><span style="font-family: "Courier New",Courier,monospace;">delete/on 3 Feb 2014</span></span> will delete the message/thread at 12 AM (00:00) on the specified date.</li>
<li><span style="background-color: cyan;"><span style="font-family: "Courier New",Courier,monospace;">delete/on 3 Feb 2014 9:00</span></span> will delete the message/thread within an hour after the specified time (I recommend that the script only runs once an hour).</li>
<li>There are a few more examples listed at the top of the source code.</li>
</ul>
<br />
One of the main ways I am using Archively for is via a filter. One of the filters I have picks out marketing style emails with a specific keyword in it, and then labels the email with <span style="background-color: #cfe2f3;"><span style="font-family: "Courier New",Courier,monospace;">delete/at EOD+2d</span></span>. To get Archively working for you, follow these easy steps:<br />
<ol>
<li>Copy the text out of my copy of the script <a href="https://script.google.com/d/1zFUIPr8rm0Ea4jkZLTO3Z2evaJx_19q2pzV-uOEeU2oHLJ0Qi1AiJ5ja/edit?usp=sharing">here</a> or <a href="https://dl.dropboxusercontent.com/u/58518258/Blog/Archively.js">here</a>.</li>
<li>Go to Google Drive and <b>create </b>a new Script. If you don't see a "Script" option, you'll need to choose "Connect more apps" and then pick Google Apps Script (also says "Script in Google Drive").</li>
<li>In the new Script, paste in the text that was copied in step 1.</li>
<li>Do a test run if you want: Select the checkEmAll function and run it.</li>
<li>Select menu Resources > Current project's triggers. Add a trigger to run <span style="font-family: "Courier New",Courier,monospace;">checkEmAll</span> hourly, and <span style="font-family: "Courier New",Courier,monospace;">cleanDbRecords</span> weekly (or some other frequencies as desired).</li>
<li>At some point you'll need to authorise the script to work with your Gmail account.</li>
<li>From within Gmail, create the base labels <span style="font-family: "Courier New",Courier,monospace;">delete</span> and <span style="font-family: "Courier New",Courier,monospace;">arkive</span>. Then you will easily be able to create labels nested under them.</li>
<li>Now you can apply labels directly, or set up filters to apply Archively labels for you.</li>
</ol>
For those of you that are interested, here is an approximate description of the grammar of the labels understood by Archively in <a href="http://en.wikipedia.org/wiki/Extended_Backus%E2%80%93Naur_Form">Extended Backus-Naur Form</a>. Note that it is not case-sensitive.<br />
<blockquote class="tr_bq">
<span style="font-family: "Courier New",Courier,monospace;">LabelText = "delete/" | "arkive/", TimeSpec;<br /> TimeSpec = EndOfSpec | AgeSpec | WhenSpec | FromNowSpec;</span><br />
<span style="font-family: "Courier New",Courier,monospace;">EndOfSpec = "TOMORROW"<br /> | (["AT", {" "}], "EO", "D"|"W"|"M"|"Y"|"FY", {</span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">TimeSpan</span>});<br /><span style="font-family: Times,"Times New Roman",serif;"> Tomorrow is an alias for EOD. The end of day (D), week (W), month (M), year (Y) and financial year (FY) are available. A month is defined as 31 days.</span><br />AgeSpec = ["WHEN "], {TimeSpan}, " OLD";<br />WhenSpec = "ON ", JavaScriptDate;<br /><span style="font-family: Times,"Times New Roman",serif;"> The description of JavaScriptDate is left to the Internet. DateTimes such as <span style="font-family: "Courier New",Courier,monospace;">"14 Jan 2014"</span>, and</span></span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: Times,"Times New Roman",serif;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: Times,"Times New Roman",serif;"> <span style="font-family: "Courier New",Courier,monospace;">"14 Jan 2014 11:00"</span></span></span> should work just fine.</span>FromNowSpec = ["IN "], {TimeSpan};</span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">TimeSpan</span> =</span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">{" "}, ["-"|"+"], {" "}, Number, {" "}, TimeUnit</span>;<br />TimeUnit = </span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">("H", ["R" | "RS" | "OUR" | "OURS"])<br /> | </span></span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">("D", ["AY" | "AYS"])<br /> | </span></span>("W", </span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">["K" | "KS" | "EEK" | "EEKS"]</span></span>)</span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><br /> | ("M", ["ONTH" | "ONTHS"])</span></span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><br /> | ("Y", </span></span></span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">["R" | "RS" | "EAR" | "EARS"]</span></span>)</span></span>;<br />Number = (Digit, {Digit}, [".", {Digit}])<br /> | (".", Digit, {Digit});<br />Digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9"; </span></blockquote>
<ol>
</ol>
<div style="text-align: left;">
Get the the script <a href="https://script.google.com/d/1zFUIPr8rm0Ea4jkZLTO3Z2evaJx_19q2pzV-uOEeU2oHLJ0Qi1AiJ5ja/edit?usp=sharing">here</a> or <a href="https://dl.dropboxusercontent.com/u/58518258/Blog/Archively.js">here</a>. Enjoy!</div>
<ol style="text-align: center;">
</ol>
<div style="text-align: center;">
<a href="http://creativecommons.org/licenses/by/4.0/deed.en_US" rel="license"><img alt="Creative Commons License" src="http://i.creativecommons.org/l/by/4.0/88x31.png" style="border-width: 0;" /></a></div>
<div style="text-align: center;">
<span property="dct:title" xmlns:dct="http://purl.org/dc/terms/">Archively</span> by <span property="cc:attributionName" xmlns:cc="http://creativecommons.org/ns#">Jonathan Johansen</span> is licensed under a <a href="http://creativecommons.org/licenses/by/4.0/deed.en_US" rel="license">Creative Commons Attribution 4.0 International License</a>.</div>
Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-79483615271179104142013-12-30T13:53:00.002-08:002013-12-30T14:07:16.895-08:00Window SnapperMany programs have a nice dividers in their GUI - and you can usually drag the divider to resize the panels on either side. I've often been a little frustrated when resizing windows to tile them to fill the screen. Perhaps a Word document on the left, a PDF in the upper right, and email in the lower right. It was quite tedious, and because of that I didn't do it often, and I feel this slightly diminished the power of windows. So I wrote <a href="https://dl.dropboxusercontent.com/u/58518258/AHK/Window%20Snapper.ahk">an AutoHotkey script</a> and now I have what I wanted.<br />
<br />
To use it, while the script is running, you can right-button drag window borders, and the script will move all neighbouring window edges at the same time. The script will grab window borders within 10 pixels (configurable) of the border/s you are right-button dragging. It also assumes a seven pixel wide window resize border, but that's also configurable at the top of the script. You can resize from edges or corners - giving you lots of power when resizing windows.<br />
<br />
The most common use-case I have is with just two windows positioned with Win+Left and Win+Right (<a href="http://blog.metalight.net/2012/11/some-random-windows-tips.html">like explained here</a>). With this script you can resize both windows effortlessly.<br />
<br />
Here's an example of it in action:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWyusVetWC-fVxeo4GGqlyEZepAn41NEC7T0FKZu6gi7YzdmPkqXEOHlf9CYCpNZy4aVfRFxz5WO00KYfYj2KZda9LA6Ed_y3PCakw4RVN7RON2MVuuPvcILI1rKCUUA4Hx6VLiBBXCJk/s1600/5+Windows+2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWyusVetWC-fVxeo4GGqlyEZepAn41NEC7T0FKZu6gi7YzdmPkqXEOHlf9CYCpNZy4aVfRFxz5WO00KYfYj2KZda9LA6Ed_y3PCakw4RVN7RON2MVuuPvcILI1rKCUUA4Hx6VLiBBXCJk/s400/5+Windows+2.png" width="400" /></a></div>
I can resize all five windows with one right-button drag, in the area where the four window corners meet in the middle of the screen. If I drag towards the upper right, I can get something like this:<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4aSuZmnIVla7nhiUuZMh2gsFqdfqVUCyZHjb19D8CfeF4Nhm0t2SX8rZGcIhsdPGtfH5uVlqdDctpugH7K13x2GRsCPMt6RinlZCL-P86dP41eDkkC5A3JhnlF961cQv0cMjzO5knwDQ/s1600/5+Windows+1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4aSuZmnIVla7nhiUuZMh2gsFqdfqVUCyZHjb19D8CfeF4Nhm0t2SX8rZGcIhsdPGtfH5uVlqdDctpugH7K13x2GRsCPMt6RinlZCL-P86dP41eDkkC5A3JhnlF961cQv0cMjzO5knwDQ/s400/5+Windows+1.png" width="400" /></a></div>
And things like this are possible too, but unsnapping window edges like I've done below with the left and right can be a little fiddly. I could potentially add something like Ctrl+Right-Click to only resize windows actually near the mouse...<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3ZwMZAKAvsOUW6cw6wAF0fz7DnplOPxDUEl0bHwPDKvOjJMHqXbKWThtdJ1Z5kRi4SPLClcogfYBR8EbFXYattLOOJ8vrWGQi79VDj718UjsauwGVQhiNaZNsT0hgpiTv86N7wlmiEhk/s1600/5+Windows+3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3ZwMZAKAvsOUW6cw6wAF0fz7DnplOPxDUEl0bHwPDKvOjJMHqXbKWThtdJ1Z5kRi4SPLClcogfYBR8EbFXYattLOOJ8vrWGQi79VDj718UjsauwGVQhiNaZNsT0hgpiTv86N7wlmiEhk/s400/5+Windows+3.png" width="400" /></a></div>
Please have a go with <a href="https://dl.dropboxusercontent.com/u/58518258/AHK/Window%20Snapper.ahk">the window snapper script</a>. Please let me know what you think after using it!<br />
<br />
<div style="text-align: center;">
<a href="http://creativecommons.org/licenses/by/4.0/" rel="license"><img alt="Creative Commons License" src="http://i.creativecommons.org/l/by/4.0/88x31.png" style="border-width: 0;" /></a></div>
<div style="text-align: center;">
<a href="https://dl.dropboxusercontent.com/u/58518258/AHK/Window%20Snapper.ahk">The script</a> is licensed under a <a href="http://creativecommons.org/licenses/by/4.0/" rel="license">Creative Commons Attribution 4.0 International License</a>.</div>
Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com1tag:blogger.com,1999:blog-1798883676384076486.post-58268202940399302602013-07-19T22:46:00.000-07:002013-07-19T22:46:00.298-07:00Engagement in the FamilyMy brother-in-law Rowan Barton is engaged to Elpida Savvidou. This is awesome news (even if not recent :-). Their engagement party is movie themed, and we've got some western style props, so I've created custom wanted posters! Here they are:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxjBqtlQ7mRMRebQ3ckWq6ns0nplJxtgo7O9RSTf0FI8XBuWCfhjDTSceYaZHIIE5CQjnzK1Y9I32Vo3pDSPbCeuQBB7SuY95g-GiPeIjLF7ZE2_DAlVTtWuzxmG-pw_Z9eSP_2UcvLhI/s1600/Wanted+Poster+Elpida.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="A wanted poster showing that Elpida is wanted alive for stealing a heart, reward $1000." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjxjBqtlQ7mRMRebQ3ckWq6ns0nplJxtgo7O9RSTf0FI8XBuWCfhjDTSceYaZHIIE5CQjnzK1Y9I32Vo3pDSPbCeuQBB7SuY95g-GiPeIjLF7ZE2_DAlVTtWuzxmG-pw_Z9eSP_2UcvLhI/s1600/Wanted+Poster+Elpida.png" title="Poster: Elpida Wanted Alive" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsEtNdcNHPVWaRJ5rYGxQy5_FbJaT3A-B4IPshAi9Olv98JzmS3wP8zkzf9kxTfFxxSpJBgTm1FA7Ok5p9XQi8l9TVEOJPqEas_Qdr0o4jHnRtoRPK6JW_4Zq0Y0gxt1EUHicxu9-jwnc/s1600/Wanted+Poster+Rowan.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="A wanted poster showing that Rowan is wanted dead or alive for parental bank robbery, reward $1000." border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjsEtNdcNHPVWaRJ5rYGxQy5_FbJaT3A-B4IPshAi9Olv98JzmS3wP8zkzf9kxTfFxxSpJBgTm1FA7Ok5p9XQi8l9TVEOJPqEas_Qdr0o4jHnRtoRPK6JW_4Zq0Y0gxt1EUHicxu9-jwnc/s1600/Wanted+Poster+Rowan.png" title="Poster: Rowan Wanted Dead or Alive" /></a></div>
<br />
Once printed we are going to brown the edges with the heat from a fire.<br />
<br />
The SVG files were created with Inkscape (Trace Bitmap is fantastic) and <a href="https://dl.dropboxusercontent.com/u/58518258/Blog/Wanted%20Poster%20Rowan.svg">are available</a> <a href="https://dl.dropboxusercontent.com/u/58518258/Blog/Wanted%20Poster%20Elpida.svg">for use</a> if you'd like. I put them in the public domain (but I'd be thrilled to hear from you if you use these). They make use of the <a href="http://www.urbanfonts.com/fonts/Playbill.htm">Playbill font</a>.<br />
<br />
I'm interested to see what other people have created. Enjoy :-)Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-20900107794679280292013-07-13T00:18:00.000-07:002013-07-13T00:18:00.715-07:00Minecraft vs Real LifeI have been digging a hole in the ground. It is just a bit more than one and a half metres deep, and around a metre in diameter. Here is the hole:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXvbqg9xXjgyTeDuTRZGisI6tIUcZNptVUckPkqmM2kltemmcg1wKYqCJl21qS9RlW1FCHHzBzZcxlrrRN0hLu5uXF3kA2akVOOzjJizNxE4PrHZWZRS5WqZMAsNKTuUxO-IzLPeaewV4/s1600/just+hole.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="A hole in the ground about 1 metre in diameter and just over one and a half metres deep." border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXvbqg9xXjgyTeDuTRZGisI6tIUcZNptVUckPkqmM2kltemmcg1wKYqCJl21qS9RlW1FCHHzBzZcxlrrRN0hLu5uXF3kA2akVOOzjJizNxE4PrHZWZRS5WqZMAsNKTuUxO-IzLPeaewV4/s400/just+hole.jpg" title="Just the Hole" width="400" /></a></div>
<br />Here is the hole with the dirt I have emptied out of the hole in view:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXBLxzbLBkDBIvq3_Q78wKx5SOrEUwrUFczpnu2t4I3tnAV0MlKC6PEZHu1vLN2AX1kYCO-DF-yLwJ7n5B3kJYtxF294AcQd3exr7PWcxcnHNvbyalJy5kSPf3HyefyUrRXbaMqyZAfS0/s1600/hole+and+piles+of+dirt.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img alt="The same hole as in the previous picture but showing the piles of 'hole' dirt around it." border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgXBLxzbLBkDBIvq3_Q78wKx5SOrEUwrUFczpnu2t4I3tnAV0MlKC6PEZHu1vLN2AX1kYCO-DF-yLwJ7n5B3kJYtxF294AcQd3exr7PWcxcnHNvbyalJy5kSPf3HyefyUrRXbaMqyZAfS0/s400/hole+and+piles+of+dirt.jpg" title="Hole and piles of dirt" width="400" /></a></div>
<br />
Here is an equivalent sized hole in Minecraft:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizbT0wyJpzCLStswCwzvT6i6xGUXwBhUYIsYeRYZwbooe2WAZE2D8VeLBtYzwRU4sDl7cyM8rrzslkoADIxM1BB5pmSDCBxuW5f_GaLE8vaV0AnXTFu49tDWdfz2Nhvn5qA-I5rhvJPNs/s1600/minecraft+hole+and+dirt.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="223" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizbT0wyJpzCLStswCwzvT6i6xGUXwBhUYIsYeRYZwbooe2WAZE2D8VeLBtYzwRU4sDl7cyM8rrzslkoADIxM1BB5pmSDCBxuW5f_GaLE8vaV0AnXTFu49tDWdfz2Nhvn5qA-I5rhvJPNs/s400/minecraft+hole+and+dirt.jpg" width="400" /></a></div>
<br />
Apart from the Minecraft hole being digital, it was also a lot neater. And it took less time to dig. The real hole above has taken several weekends of digging - probably close to 20 hours of digging. The Minecraft hole took around 20 seconds, that's including deciding where to dig. Perhaps that's one reason why games like Minecraft are enjoyable to play - they let you do mundane things really quickly.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com15tag:blogger.com,1999:blog-1798883676384076486.post-40965693456860749972013-07-06T00:09:00.000-07:002013-07-06T00:09:00.057-07:00Bits of MinecraftMinecraft has sunk a lot of my time over the few years it's been around. Here are some of the things I've done in it (in order of construction):<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirQOD7FHkiA78PtVXWGZLoisPDH77OGVU5OGtgfhbobCem4ewyJSWUkJGqHpqSqxDNF4MGbWuFjdQt2CbNYMahFbYU4CKd2d4JILcUgOHnc6dt8zyqXQ_XJtNAfKmQnu85F81cTyvXa5c/s1600/rainbow+cake.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="A rainbow made of wool is visible to the left, and a large woolen cake lurks in the fog to the right." border="0" height="220" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEirQOD7FHkiA78PtVXWGZLoisPDH77OGVU5OGtgfhbobCem4ewyJSWUkJGqHpqSqxDNF4MGbWuFjdQt2CbNYMahFbYU4CKd2d4JILcUgOHnc6dt8zyqXQ_XJtNAfKmQnu85F81cTyvXa5c/s400/rainbow+cake.jpg" title="Rainbow ... and cake!" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Rainbow! ... and cake</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img alt="A triple helix with hanging vines made of dirt rises into the sky in front of a seemingly floating land." border="0" height="312" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiA3BDDes3YxvHR8smUbjQtSsbR02PR4taffnTUA3T7huYP-rhuNhsKdgcYEBTQPq8K9B759z3GlfSZTchhhI7_ms2mVWcmE6KlG0iUg3RtN1dVjXfP0xGulpCgz9MmCg7hz3nuEhUyJQg/s400/tripleHelix+overworld.jpg" style="margin-left: auto; margin-right: auto;" title="Triple Helix" width="400" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Triple helix near an overworld plate</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE_jGpxW9Var4H1Ude23yO71ma7ZXBUkQmowgE-qMJJ_0eFqNTCYwTDGFUw9LtXqWEp79gsDYuDLv5uHALFEbhH5gIz9lJyt_GMf2BRZ78Q4r1Vr0OuvaAITOt4f3kdJLTHsf_szHiJ1w/s1600/dish+craft.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="From my overworld you can see my home base tower on the left, satellite dish in the centre and the word "Craft" made of wool on the right." border="0" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhE_jGpxW9Var4H1Ude23yO71ma7ZXBUkQmowgE-qMJJ_0eFqNTCYwTDGFUw9LtXqWEp79gsDYuDLv5uHALFEbhH5gIz9lJyt_GMf2BRZ78Q4r1Vr0OuvaAITOt4f3kdJLTHsf_szHiJ1w/s400/dish+craft.jpg" title="Home, Satellite dish and "Craft"" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Home, satellite dish and "Craft"</td></tr>
</tbody></table>
<div style="text-align: left;">
The rainbow, triple helix and satellite dish were all planned using Lisp. Here's some Lisp code you can use to plan rainbows:</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "Courier New",Courier,monospace;">(<b>loop </b>with freq = (list)<br /> and reach = (1+ 20)<br /> and width = 8<br /> for j from reach downto 0<br /> do <span style="color: purple;">(<b>loop </b>for i from (- reach) to reach<br /> for r = (round (sqrt (+ (square i) (square j))))<br /> for c = <span style="color: #38761d;">(cond ((= i j 0) <b>#\+</b>)<br /> ((< r (- reach width)) <b>#\-</b>)<br /> ((<= r (1- reach)) <b>(- r (- reach width))</b>)<br /> (t <b>#\Space</b>))</span><br /> when (not (eql #\Space c))<br /> do (aif (cdr (assoc c freq))<br /> (incf (car it))<br /> (push (list c 1) freq))<br /> when (or (minusp i) (not (eql #\Space c))) do (princ c))</span><br /> do (terpri)<br /> finally (return freq))</span></div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
It produces output like this (this one's a small version to fit in the width of the blog):</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
<span style="font-family: "Courier New",Courier,monospace;"> 777777777<br /> 777666666666777<br /> 7766655555555566677<br /> 77665554444444445556677<br /> 7665544433333333344455667<br /> 766544433322222223334445667<br /> 76554433222111111122233445567<br /> 7655433221110000000111223345567<br /> 7655433211000-------0001123345567<br /> 766543321100-----------001123345667<br /> 7654332100---------------0012334567<br /> 7654432100-----------------0012344567<br /> 765432110-------------------011234567<br /> 765443210---------------------012344567<br /> 765432100---------------------001234567<br /> 76543210-----------------------01234567<br /> 765433210-----------------------012334567<br /> 76543210-------------------------01234567<br /> 76543210-------------------------01234567<br /> 76543210-------------------------01234567<br /> 76543210------------+------------01234567<br />((#\+ 1) (#\- 256) (0 45) (1 45) (2 43) (3 57) (4 57) (5 57) (6 59) (7 57))</span><br />
<br />
The last bit is a count of each block type so you know how much to gather of each type. Three dimensional objects like the dish and triple helix use more code which I can post if people are interested.<br />
<br />
P.S. Don't spend too much time playing computer games.</div>
Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com2tag:blogger.com,1999:blog-1798883676384076486.post-46320231394821342852013-06-29T21:20:00.000-07:002013-06-29T21:20:00.299-07:00Diode PN Junction ExplainedI never felt like I properly understood how the PN junction in a diode works. So I looked it up and came across some explanations that really helped me understand it better. I've put it all into a diagram. But let's introduce some of the concepts first.<br />
<br />
A diode is made of a semiconductor (like Silicon) with two regions. The semiconductor makes up a crystal. One region in the crystal has been doped with atoms that have a spare electron when in the crystal lattice. It is known as the N region. The other region in the crystal has been doped with atoms that have spare room for an electron when in the crystal lattice (the spare spots are known as holes). It is known as the P region. That's where the name PN junction comes from.<br />
<br />
The N region with its spare electrons conducts via movement of these spare electrons (the electrons are the charge carriers in an N region). The electrons are the charge carriers. Conversely, the P region conducts via the movement of the 'holes' (the holes are the charge carriers in a P region). As an aside, undoped semiconductors don't conduct as well because they don't have mobile charge carriers.<br />
<br />
An important note to remember is that while the regions may be called N and P, this does not mean that they are overall positively or negatively charged. The regions have an overall neutral charge. Following on from that, if you were to take away the electrons in an N region, the crystal structure would be positively charged. The opposite would occur if you filled the holes in a P region with electrons.<br />
<br />
So, with that explanation, here's the diagram:<br />
<div style="margin: 10px 10px 10px 10px; text-align: center;">
<iframe height="840px" src="https://dl.dropboxusercontent.com/u/58518258/Blog/PNjunctionDiode.svg" style="border: none; overflow: hidden;" type="text/xml" width="438px">Awesome Diagram!!! .... Oh, this is an error message. If you are reading this, something broke. You may need to upgrade your browser.</iframe></div>
<div style="text-align: left;">
So the depletion region gives a potential barrier (from the fixed charges). The width of the depletion region (and thus also the size of the potential barrier) depends on the applied potential (in effect, it depends on the direction of the <i>attempted</i> flow of current).<br />
<br /></div>
<div style="text-align: left;">
Thanks to:</div>
<ul>
<li><a href="http://library.thinkquest.org/12666/junction.html">http://library.thinkquest.org/12666/junction.html</a></li>
<li><a href="http://en.wikipedia.org/wiki/Diode">The Wikipedia page about diodes</a></li>
<li><a href="http://uvdiv.blogspot.com.au/2009/08/how-to-create-svg-graphics-in-blogger.html">The Capacity Factor for the SVG graphics in Blogger instructions</a></li>
<li>And <a href="http://inkscape.org/">Inkscape</a>! </li>
</ul>
<div style="text-align: center;">
<a href="http://creativecommons.org/licenses/by-sa/3.0/deed.en_US" rel="license"><img alt="Creative Commons License" src="http://i.creativecommons.org/l/by-sa/3.0/88x31.png" style="border-width: 0;" /></a><br />
The <a href="https://dl.dropboxusercontent.com/u/58518258/Blog/PNjunctionDiode.svg"><span property="dct:title" xmlns:dct="http://purl.org/dc/terms/">PN Junction Explained</span></a> diagram by <a href="http://blog.metalight.net/" property="cc:attributionName" rel="cc:attributionURL" xmlns:cc="http://creativecommons.org/ns#">Jonathan F Johansen</a> is licensed under a <a href="http://creativecommons.org/licenses/by-sa/3.0/deed.en_US" rel="license">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</div>
Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-42969055458629983032013-06-22T04:00:00.000-07:002013-06-22T04:00:06.543-07:00Hard to Find Excel TidbitA short post this week. I recalled that there was a syntax for Excel ranges in VBA. I searched online, but couldn't find much, so here is the tidbit: Ranges can be specified using square brackets. If you used named ranges a lot, this turn out quite nice. So if you have a named range called ImportantInfo, you can refer to it as ... <span style="color: purple;"><b><span style="font-family: "Courier New",Courier,monospace;">[ImportantInfo]</span></b></span>! And it may not provide the method list when you type a full stop after it, but it IS a range object, so you can use it like this:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"> Answer = </span><span style="font-family: "Courier New",Courier,monospace;"><span style="color: purple;"><b><span style="font-family: "Courier New",Courier,monospace;">[ImportantInfo]</span></b></span>.Offset(RowCount, ColumnCount).Text</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> MsgBox "The cell Sheet2!E3 contains """ & <span style="color: purple;"><b>[Sheet2!E3]</b></span> & """."</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> Dim Cell As Range<br /> For Each Cell In <span style="color: purple;"><b>[B1:B3]</b></span><br /> MsgBox Cell.Text<br /> Next Cell</span><br />
<br />
One of the reasons I think it's neat when used for named ranges is that with most named ranges in square brackets, you don't have to specify the sheet to disambiguate it. That makes for shorter, and thus easier to read code.<br />
<br />
Enjoy!Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-77735604391639772132013-06-15T03:31:00.000-07:002013-06-15T03:31:00.562-07:00Linked Lists in VBA (Excel)I use Microsoft Excel quite a bit. And recently we had a challenge at work to validate lane use signal displays using conflict matrices. Well, I had some Lisp written to generate sequences given a set of allowed 'transitions'. So I wanted to put that logic into Excel, which meant VBA. I thought it would be quick, but it took about two and a half full days of work... Part of porting over my logic was creating a linked list class named "List" in VBA. It is my first VBA class module (yay!). Here's the code in the "Node" class module:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: purple;"><span style="color: lime;">'' Linked Lists in VBA is released under a <a href="http://opensource.org/licenses/bsd-license.php">BSD licence</a>. Author: Jonathan F Johansen</span></span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: purple;">Option Explicit</span><br /><span style="color: #bf9000;">Public Car As Variant<br />Public Cdr As List</span><br /><br /><span style="color: blue;">Public Function</span> <b>ToString</b>() As String<br /> <b>ToString </b>= "[" & PlainListString() & "]"<br /><span style="color: blue;">End Function</span><br /><br /><span style="color: blue;">Public Function</span> <b>PlainListString</b>() As String<br /> If Cdr Is Nothing Then<br /> <b>PlainListString </b>= CStr(Car)<br /> Else<br /> <b>PlainListString </b>= CStr(Car) & ", " & Cdr.<b>PlainListString</b>()<br /> End If<br /><span style="color: blue;">End Function</span></span><br />
<br />
I had more in the class module, but took most of the methods out of there because I wanted to treat <b><span style="font-family: "Courier New",Courier,monospace;">Nothing</span></b> as the empty list. Here are the functions from a separate module:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: purple;"><span style="color: lime;">'' </span></span></span><span style="font-family: "Courier New",Courier,monospace;"><span style="color: purple;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: purple;"><span style="color: lime;">Linked </span></span></span>Lists in VBA is released under a <a href="http://opensource.org/licenses/bsd-license.php">BSD licence</a>. Author: Jonathan F Johansen</span> </span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: purple;">Option Explicit</span><br /><br /><span style="color: lime;">'' Making Lists:</span><br /><br /><span style="color: blue;">Function</span> <b>Cons</b>(Item As Variant, Optional Rest As List) As List<br /> Set Cons = New List<br /> Cons.Car = Item<br /> Set Cons.Cdr = Rest<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>MakeList</b>(ParamArray Items() As Variant) As List<br /> On Error GoTo ZeroLength ' Leaving MakeList as Nothing.<br /> Dim I As Long<br /> For I = UBound(Items) To LBound(Items) Step -1<br /> Set MakeList = Cons(Items(I), MakeList)<br /> Next I<br />ZeroLength:<br /><span style="color: blue;">End Function<br /><br /><span style="color: lime;">'' Working with Lists</span><br /><br />Function</span> <b>Append</b>(aList As List, OtherList As List) As List<br /> If aList Is Nothing Then<br /> Set <b>Append </b>= OtherList<br /> ElseIf OtherList Is Nothing Then<br /> Set <b>Append </b>= aList<br /> ElseIf aList.Cdr Is Nothing Then<br /> Set <b>Append </b>= Cons(aList.Car, OtherList)<br /> Else<br /> Set <b>Append </b>= Cons(aList.Car, <b>Append</b>(aList.Cdr, OtherList))<br /> End If<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>Reverse</b>(aList As List, Optional OntoFrontOf As List) As List<br /> If aList Is Nothing Then<br /> Set <b>Reverse </b>= OntoFrontOf<br /> Else<br /> Set <b>Reverse </b>= <b>Reverse</b>(aList.Cdr, Cons(aList.Car, OntoFrontOf))<br /> End If<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>Length</b>(aList As List) As Long<br /> If aList Is Nothing Then Exit Function <span style="color: lime;">'Returning 0</span><br /> <b>Length </b>= 1 + <b>Length</b>(aList.Cdr)<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>Member</b>(Item As Variant, aList As List) As Boolean<br /> If aList Is Nothing Then Exit Function<br /> If aList.Car = Item Then<br /> <b>Member </b>= True<br /> ElseIf aList.Cdr Is Nothing Then<br /> <b>Member </b>= False<br /> Else<br /> <b>Member </b>= <b>Member</b>(Item, aList.Cdr)<br /> End If<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>Replace</b>(OldItem As Variant, NewItem As Variant, aList As List) As List<br /> If aList Is Nothing Then<br /> ElseIf aList.Cdr Is Nothing Then<br /> If aList.Car = OldItem Then<br /> Set <b>Replace </b>= Cons(NewItem)<br /> Else<br /> Set <b>Replace </b>= aList<br /> End If<br /> Else<br /> If aList.Car = OldItem Then<br /> Set <b>Replace </b>= Cons(NewItem, <b>Replace</b>(OldItem, NewItem, aList.Cdr))<br /> Else<br /> Set <b>Replace </b>= Cons(aList.Car, <b>Replace</b>(OldItem, NewItem, aList.Cdr))<br /> End If<br /> End If<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>Remove</b>(Item As Variant, aList As List) As List<br /> If aList Is Nothing Then Exit Function<br /> If Item = aList.Car Then<br /> Set <b>Remove </b>= <b>Remove</b>(Item, aList.Cdr)<br /> Else<br /> Set <b>Remove </b>= Cons(aList.Car, <b>Remove</b>(Item, aList.Cdr))<br /> End If<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>Count</b>(Item As Variant, List As List) As Long<br /> If List Is Nothing Then Exit Function<br /> If List.Car = Item Then <b>Count </b>= 1<br /> <b>Count </b>= <b>Count </b>+ <b>Count</b>(Item, List.Cdr)<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>CountMaxConsecutive</b>(Item As Variant, List As List) As Long<br /> If List Is Nothing Then Exit Function<br /> Dim Rest As List, Count As Long<br /> Set Rest = List<br /> Do Until Rest Is Nothing<br /> If Rest.Car = Item Then<br /> Count = Count + 1<br /> Else<br /> Count = 0<br /> End If<br /> If Count > <b>CountMaxConsecutive </b>Then <b>CountMaxConsecutive </b>= Count<br /> Set Rest = Rest.Cdr<br /> Loop<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>CellTextToList</b>(aRange As Range) As List<br /> Dim I As Long<br /> If IsEmpty(aRange) Then Exit Function<br /> For I = aRange.Cells.Count To 1 Step -1<br /> Set <b>CellTextToList </b>= Cons(aRange.Cells(I).Text, <b>CellTextToList</b>)<br /> Next I<br /><span style="color: blue;">End Function<br /><br />Function</span> <b>ListToRow</b>(aList As List, Target As Range) As Range<br /> Dim List As List<br /> Set List = aList<br /> Set <b>ListToRow </b>= Target<br /> Do Until List Is Nothing<br /> <b>ListToRow </b>= List.Car<br /> Set <b>ListToRow </b>= <b>ListToRow</b>.Offset(0, 1)<br /> Set List = List.Cdr<br /> Loop<br /><span style="color: blue;">End Function</span></span><br />
<br />
I found it useful, but it could do with a few more utilities. One interesting thing is that looping over a list isn't to complex, as you can see in the last function above. You just declare a local List variable and then use a <span style="font-family: "Courier New",Courier,monospace;">Do Until localList Is Nothing</span>, and at the end of the loop body, <span style="font-family: "Courier New",Courier,monospace;">Set localList = localList.Cdr</span>. If you don't declare a local list, but modify the argument, you'll find that the list is chewed up in the caller's scope too...<br />
<br />
Here are some examples of the List in action:<br />
Option Explicit<br /><br /><span style="font-family: "Courier New",Courier,monospace;"><span style="color: blue;">Sub </span><b>TestLinkedLists</b>()<br /> MsgBox <b>Cons</b>("a", <b>Cons</b>("b")).<b>ToString</b><br /> MsgBox <b>Length</b>(<b>MakeList</b>(1, 2, 3, 4, 5))<br /> MsgBox <b>Reverse</b>(<b>MakeList</b>(1, 2, 3, 4, 5)).<b>ToString</b><br /> MsgBox <b>MakeList</b>(1, 2, 3, 4, 5).<b>ToString</b><br /> MsgBox <b>Member</b>(4, <b>MakeList</b>(1, 2, 3, 4, 5))<br /> MsgBox <b>Member</b>(4, Nothing)<br /> MsgBox <b>Append</b>(<b>MakeList</b>(1, 2, 3, 4), <b>MakeList</b>(5, 6, 7)).<b>ToString</b><br /> MsgBox <b>Replace</b>(4, "four", <b>MakeList</b>(1, 2, 3, 4, 5)).<b>ToString</b><br /> MsgBox <b>Remove</b>(3, <b>MakeList</b>(1, 2, 3, 4, 5)).<b>ToString</b><br /> MsgBox <b>Count</b>(True, <b>MakeList</b>(False,True,True,True,False,True))<br /> MsgBox <b>CountMaxConsecutive</b>(True, _</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <b>MakeList</b>(False, True, True, True, False, True))<br /><span style="color: blue;"><span style="color: black;"> MsgBox <b>CellTextToList</b>(Range("A2:A6")).<b>ToString</b><br /> MsgBox "List output to B2, range returned is " _<br /> & <b>ListToRow</b>(<b>CellTextToList</b>(Range("A2:A6")), Range("C2")).Address _<br /> & " ready to go for something else..."</span><br />End Sub</span></span><span style="color: blue;"> </span><br />
<br />
If you've read the code, you might notice the liberal use of recursion, and the use of functional style. I used recursion a lot in the spreadsheet, and I think this List class helped a lot.<br />
<br />
The code on this page is collected into an Excel spreadsheet for convenience too. <a href="https://dl.dropboxusercontent.com/u/58518258/VBA/Linked%20Lists%20in%20VBA.xlsm">You can download it from here</a>. As noted in the code comments, the code is released under <a href="http://opensource.org/licenses/bsd-license.php">the BSD license</a> - and I'd love to hear from you if you use it or extend it. Enjoy!Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com4tag:blogger.com,1999:blog-1798883676384076486.post-10654054456509009262013-06-08T18:24:00.000-07:002013-06-08T18:24:00.400-07:00Excel Table to Jira TableExcel table, meet Jira :-). After writing <a href="http://blog.metalight.net/2013/06/clipboard-processing-with-autohotkey.html">the previous AutoHotkey script to convert the clipboard contents to a comma separated list</a>, I wrote this one. It makes constructing Jira tables a breeze.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: lime;">;;; Converts a copied table from Excel into Jira format</span><br />#+j::<br /> <b>StringReplace</b>, ForFirstLine, Clipboard, `r`n, §<br /> <b>StringSplit</b>, ForFirstLine, ForFirstLine, §<br /> <b>StringReplace</b>, ForFirstLine1, ForFirstLine1, %<b>A_Tab</b>%, ||, All<br /> <b>StringReplace</b>, ForFirstLine2, ForFirstLine2, %<b>A_Tab</b>%, |, All<br /> ForFirstLine2 := <b>RTrim</b>(ForFirstLine2, "`r`n")<br /> <b>StringReplace</b>, ForFirstLine2, ForFirstLine2, `r`n, |`r`n|, All<br /> Clipboard := "||" . ForFirstLine1 . "||`r`n|" . ForFirstLine2 . "|"<br /> <b>Send </b>^v<br />Return</span><br />
<br />
To use it, just press Windows+Shift+J (but that's easily changed). It puts double pipes on the first line, and single pipes on other lines.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com10tag:blogger.com,1999:blog-1798883676384076486.post-39915065486634828702013-06-01T18:01:00.000-07:002013-06-01T18:01:00.190-07:00Clipboard Processing with AutoHotkeyI've been doing a lot of text processing recently, and a lot of it has been to convert a column of cells from Excel into a comma separated list. Well, <a href="http://blog.metalight.net/2013/05/notepad-find-and-replace.html">I used to do that with Notepad++</a>, but last week I bit the bullet and wrote an AutoHotkey script to do it for me. Without further ado, here are the goods:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #990000;">#v::<br /> <b>StringReplace</b>, Clipboard, Clipboard, `r`n, `,%<b>A_Space</b>%, All<br /> Clipboard := <b>RTrim</b>(Clipboard, ", `n") </span><span style="color: lime;">; Gets rid of the annoying trailing newline that Office programs put in.</span><br /><span style="color: #990000;"> <b>Send </b>^v<br />Return</span></span><br />
<br />
It will paste the converted clipboard contents when you press Windows+V. Also, I found a way to get text/content copied from MS Office to plain, plain text by removing the trailing newline character.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-87421382843929770152013-05-24T17:38:00.000-07:002013-05-25T03:35:29.938-07:00Notepad++ Find and ReplaceI think Notepad++ is a great program. I use it a lot at work and at home. I have used it to process text in various ways. I really like Notepad++'s find and replace options, especially <a href="http://notepad-plus-plus.org/news/notepad-6.0-release.html">since the Regular Expression engine was updated to PCRE</a>. A <a href="http://markantoniou.blogspot.com.au/2008/06/notepad-how-to-use-regular-expressions.html">great post on Notepad++'s find and replace can be found on Mark's Speechblog</a>. In the examples below, don't type in the double quotes. Here are a few Find and Replace searches I have found useful:<br />
<br />
This one turns new lines into commas with spaces. I use it to convert a column of Excel data into text as a comma separated list. I've since written an AutoHotkey script to do this too (because I do this so often), which will be the topic of a future post.<br />
<b>Search Mode: </b>Extended<br />
<b>Find: </b>"\r\n"<br />
<b>Replace with:</b> ", "<br />
<br />
This finds a specific second column of freeform text from several other columns with digits. The second find string converts a line like "11937577 M0609/VD06 108721 11933802 198024 11933835" into just "M0609/VD06".<br />
<b>Search Mode:</b> Regular expression<br />
<b>Find:</b> "\d+ +(.+)" <i>and</i> "\d+ +(.+) +\d+ +\d+ +\d+ +\d+"<br />
<b>Replace with:</b> "\1"<br />
<br />
This one uses start and end of line anchors to ensure the whole line is matched, and grabs the last column. It converts something like "108608 Left turn MVT from Road SEB to Ave NEB NULL 9 7774/SEB/LQ" into "7774/SEB/LQ".<br />
<b>Search Mode:</b> Regular expression<br />
<b>Find:</b> "^.* +(.+)$"<br />
<b>Replace with:</b> "\1"<br />
<br />
This one puts a capital M in front of lines that begin with a digit.<br />
<b>Search Mode:</b> Regular expression<br />
<b>Find:</b> "^(\d)"<br />
<b>Replace with:</b> "M\1"<br />
<br />
This one splits some text in a specific tabular form into separate lines.<br />
<b>Search Mode:</b> Regular expression<br />
<b>Find:</b> "(\d+/[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t(SB|NB)\t[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t[^\t\r\n]*\t)"<br />
<b>Replace with:</b> "\1\r\n"<br />
<br />
This one removes a tab from the end of a line if it has any. I should have put the last \t in the above regular expression outside of the group, as in "(...[^\t\r\n]*)\t".<br />
<b>Search Mode: </b>Regular expression<br />
<b>Find:</b> "\t$"<br />
<b>Replace with:</b> "" <i>(nothing)</i><br />
<br />
For this find and replace, I wanted to wrap everything on non-empty lines with some other text (in this case it's for a custom SQL query).<br />
<b>Search Mode:</b> Regular expression<br />
<b>Find: </b>"^(.+)$"<br />
<b>Replace with:</b> " or v.Identifier like '%\1%'"<br />
<br />
Have fun with Notepad++!Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-70510262568211003382013-02-16T23:38:00.000-08:002013-02-16T23:38:43.195-08:00Simple Glossaries in LaTeXI use <a href="http://www.latex-project.org/">LaTeX</a> (via <a href="http://miktex.org/">MikTeX</a>) and <a href="http://www.texniccenter.org/">TeXnicCenter</a>
a bit, starting from when I did my PhD. It's a great document
preparation system which has some annoying sides, but I won't go down
that path. I tried to set up a glossary in a document recently, and it
wasn't obvious to me how to do that. I did get it working though. Here's
what I did, so that others (including myself) don't have to figure it
out again:<br />
<ol>
<li>Follow the steps provided at <a href="http://texblog.org/2007/11/01/glossary-in-latex/">LaTeX Matters</a>, namely:</li>
<ol>
<li> Put two lines into your preamble (before <span style="color: #674ea7;"><span style="font-family: "Courier New",Courier,monospace;">\begin{document}</span></span>):<br /> <span style="color: #674ea7;"><span style="font-family: "Courier New",Courier,monospace;">\usepackage{glossary}<br />\makeglossary</span></span></li>
<li>When you define or introduce certain terms, wrap them in a <span style="color: #674ea7;"><span style="font-family: "Courier New",Courier,monospace;">\glossary</span></span> command like so:<br /><span style="color: #674ea7;"><span style="font-family: "Courier New",Courier,monospace;">\glossary{name={entry name}, description={entry description}}</span></span><br />The inside curly braces are only necessary if you have commas in the entries.</li>
<li>Place this command where you want the glossary to appear:<br /><span style="color: #674ea7;"><span style="font-family: "Courier New",Courier,monospace;">\printglossary</span></span></li>
<li>If you want your glossary to have an entry in the Table of Contents, then put this with the previous line:<span style="color: #674ea7;"><span style="font-family: "Courier New",Courier,monospace;"><br />\addcontentsline{toc}{chapter}{Glossary}</span></span></li>
<li>Then, instead of running a command as described in the post, follow the next step, which is equivalent, but for TeXnicCenter.</li>
</ol>
<li>Prompted by Archiddeon's <a href="http://latex-community.org/forum/viewtopic.php?f=31&t=945">comment in a LaTex forum</a>, in TeXnicCenter, add a post-processing step to a build profile:</li>
<ol>
<li>Select the <i>Build</i> menu then choose <i>Define Output Profiles...</i></li>
<li>On the left, select a profile you want to start from</li>
<li>Click the Copy button down below, enter a new name for the profile and click OK</li>
<li>Then click on the <i>Postprocessor</i> tab</li>
<li>Create a new postprocessor step by clicking the little "new folder" icon at the top right</li>
<li>Then enter a name like "Prepare the glossary" and the following:<br />Executable: <i>makeindex</i><br />Arguments: <i>"%tm.glo" -s "%tm.ist" -t "%tm.glg" -o "%tm.gls"</i></li>
</ol>
<li>Click OK until you're back at the main window!</li>
</ol>
Then
you should be able to select the new profile and generate the document
with a glossary! I'd run it 2-3 times to let the page numbers settle.
Joy!Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-35989182330459881482013-02-08T23:37:00.003-08:002013-02-08T23:39:53.332-08:00The 147 Problem from Programming Praxis<a href="http://programmingpraxis.com/">Programming Praxis</a> is a great site. The 147 problem <a href="http://programmingpraxis.com/2013/02/05/the-147-puzzle/">was recently posted there</a>, and I tackled it with a bit too much time... Following is the code, with discussion.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">(defun <b>sum1/</b> (s)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #990000;">"Read the name as Sum the Inverses" </span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> (apply #'+ (mapcar #'/ s)))</span><br />
<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">(defun <b>limits </b>(n)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #990000;">"I took the limits discussion on the site a bit further..."</span><br /> (loop for i from n downto 1<br /> for prod = (apply #'* prods)<span style="color: #38761d;">; Produces 1 to start with</span><br /> for prods = (cons (1+ prod) prods)<br /> for min = (min (car prods) n)<br /> for max = (max (* i prod) n)<br /> collect (list min max)))</span><br />
<br />
When calling <span style="font-family: "Courier New",Courier,monospace;">limits</span> with n = 5, we get <span style="font-family: "Courier New",Courier,monospace;">((2 5) (3 8) (5 18) (5 84) (5 1806))</span> which shows the maximum ranges of each number we'll search for. The actual search for solutions to 1/a+1/b+1/c+1/d+1/e = 1 then looks like this:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">(defun <b>search1 </b>(n &optional givens limits)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #990000;">"Actually finds all of the valid solutions to the 147</span></span><br />
<span style="color: #990000;"><span style="font-family: "Courier New",Courier,monospace;">problem with n numbers. Call it without the optional arguments</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #990000;">to start it off."</span><br /> (let ((limits (if (null givens) (limits n) limits)))</span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"> ;; Limits is whittled down during the recursion,</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"> ;; so detect starting off by looking at givens.</span><br /> (if (= n (length givens))<br /> (if (= 1 (sum1/ givens))<br /> (list (reverse givens)))<br /> (loop for next from (max (caar limits)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> (if givens (car givens) 0))<br /> to (cadar limits)<br /> for s = (cons next givens)<br /> until (or (every (lambda (i) (> i n)) s)<br /> (and (not (cdr limits)) (< (sum1/ s) 1)))<br /> appending (search1 n s (cdr limits))))))</span><br />
<br />
<br />
<br />
This code times how long it takes to solve the first few solutions before the times get too big:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">(time (loop for n from 0 to 5 collect (nreverse (search1 n))))</span><br />
<br />
<br />
Which gave 4.1 seconds on my computer.<br />
<br />
Note that the code works for n = 0 and 1 (producing the empty list, and a single solution: 1, respectively). As some other people have mentioned, Common Lisp is well thought out. I think this also supports that thought, as I didn't design the algorithm specifically to handle cases n = 0 and 1.<br />
<br />
And lastly, the following code finds the smallest distinct solutions, <a href="http://programmingpraxis.com/2013/02/05/the-147-puzzle/">as described at Programming Praxis</a>:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">(sort</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> (remove nil</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> (mapcar (lambda (s)</span><br />
<span style="font-family: "Courier New",Courier,monospace;"> (if (apply #'/= s)<span style="color: #38761d;">; Distinctness</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> (cons s (apply #'+ s))))<span style="color: #38761d;">; Sum the denominators</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"> (search1 5)))<br /> #'< :key #'cdr)<span style="color: #38761d;">; Sort by the sum of denominators</span></span><br />
<br />
Which gives <span style="font-family: "Courier New",Courier,monospace;">(3 4 5 6 20)</span>, confirming our solution.<br />
<br />
Happy coding!Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-8059528502615090912013-02-02T23:41:00.000-08:002013-02-02T23:41:00.600-08:00Solving the Discretised Traffic Model EquationsThis post follows on from when <a href="http://blog.metalight.net/2012/12/discretising-base-traffic-model.html">we discretised our traffic model equations</a>. We now solve them in this post.<br />
<br />
The solving process is quite simple since we avoided most references to the future values of variables. If we did, we'd have to use matrices to solve the discretised model equations. As it is, we can simply calculate each value separately.<br />
<br />
The code is modeled around each cell, so here's the discretised cell equation: $$\rho(x_i,t_f) = \rho(x_i,t_c) -
\frac{t_f-t_c}{x_{i+}-x_{i-}}\left(\rho(x_{i+},t_c) v(x_{i+},t_c) -
\rho(x_{i-},t_c) v(x_{i-},t_c)\right).$$ where<br />
\(\rho\) = vehicular density (veh/m);<br />
\(t\) = time (s);<br />
\(t_c\) = the current time (s);<br />
\(t_f\) = the future time (s);<br />
\(x\) = distance (m) along road;<br />
\(i\) = the index of the current cell, ranging from 1 to \(n\);<br />
\(x_i\) = the location of the 'centroid' of the current cell (m);<br />
\(x_{i-}\) = the left (upstream) boundary of the current cell<br />
\(x_{i+}\) =<br />
\(v_f\) = free flow speed (m/s);<br />
\(\rho_j\) = jam density (veh/m), the average vehicles per metre in stationary traffic; and<br />
\(v\) = vehicle speed (m/s), and is given by: \(v = v_f(1-\rho/\rho_j)\).<br />
<br />
The left boundary is given by: $$\rho(0,t) = \rho_j/4.$$<br />
<br />
Oh, and in case it isn't clear, the flow of traffic is in the direction of increasing \(x\) , which is to the right. That means that upstream is to the left, and downstream is to the right.<br />
<br />
The above equations have been implemented in Common Lisp, with MathP (but I'll wait till the end to show the final code). It outputs the values scaled up by 1000 for convenience. To call it, we evaluate something like this:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;">(step-simulation :road-length 1000 :n 20 :dt 1.0 :time-run 200)</span></span><br />
<br />
Great! So, let's look at the results. Here is a visualisation of the results for the above simulation:<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjluWsxgVhqEq6gv65QjrPy2mcw-sycr5k1iTLbG3wCdmiZMoqxrGtA0lzzN6Sj76fb6-os27N8CHAtBDCmAhadHF2zycbVk8B6Ny4jGOOc33JK4blYjuDYoDrmaHEMpzKwZYQe48g7JzY/s1600/plain+traffic+model+solution.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjluWsxgVhqEq6gv65QjrPy2mcw-sycr5k1iTLbG3wCdmiZMoqxrGtA0lzzN6Sj76fb6-os27N8CHAtBDCmAhadHF2zycbVk8B6Ny4jGOOc33JK4blYjuDYoDrmaHEMpzKwZYQe48g7JzY/s640/plain+traffic+model+solution.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Initial traffic simulation results. Time increases from top to bottom, distance increases from left to right. Light traffic is green, medium traffic is yellow, and heavier traffic is red.</td></tr>
</tbody></table>
<br />
<br />
Not so good... there are fluctuations in the solution, causing negative vehicle densities. Thankfully, that can be fixed with an <a href="http://en.wikipedia.org/wiki/Upwind_scheme">Upwind scheme</a>. In our case, we just move the centroid more upstream within the cell. This removes the fluctuations, but probably increases error elsewhere in the simulation. The results with the Upwind scheme are:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0zMp4bQwcRVovSlAEgOxuS-6sjI2WkJoZ-Rqqug6m_JfcGlVBIQLC6Ho_6dSQcLohgjqFPFuT0Zh6hKeYlFUexfcPGGQTCZp625-1m1iEHzrIOL9h6duRJr8I1H2Je2FP7-HeaPYKyLA/s1600/upwind+traffic+model+solution.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="346" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0zMp4bQwcRVovSlAEgOxuS-6sjI2WkJoZ-Rqqug6m_JfcGlVBIQLC6Ho_6dSQcLohgjqFPFuT0Zh6hKeYlFUexfcPGGQTCZp625-1m1iEHzrIOL9h6duRJr8I1H2Je2FP7-HeaPYKyLA/s640/upwind+traffic+model+solution.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">"Upwind" traffic simulation results. Time increases from top to bottom, distance
increases from left to right. Light traffic is green, medium traffic is
yellow, and heavier traffic is red.</td></tr>
</tbody></table>
<br />
Looking good. The traffic on the left fills the road over time, and there are no fluctuations. <br />
<br />
The final code to implement this is:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;">(defparameter *free-flow-speed* (/ 60 3.6)<span style="color: lime;">; = 60 km/h</span></span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"><span style="color: black;"> </span><span style="color: #990000;">"Speed (m/s) of freely flowing, low density traffic."</span>)<br />(defparameter *jam-density* (/ 7.0)<span style="color: lime;">; = 1 veh every 7 m</span></span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"> <span style="color: #990000;">"Jam density (veh/m), the average vehicles per metre in stationary traffic."</span>)<br />(defparameter *road-length* 1000.0<span style="color: lime;">; = 1 km</span></span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"> <span style="color: #990000;">"Length (m) of road being simulated."</span>)<br />(defparameter *cell-count* 10</span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"> <span style="color: #990000;">"Number of cells road is split into for simulation."</span>)</span></span><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;">(defun step-simulation (&key<br /> (vf *free-flow-speed*)<br /> (pj *jam-density*)<br /> (road-length *road-length*)<br /> (n *cell-count*)<br /> (dt 1.0); Time step in seconds.<br /> (time-run 10.0)<span style="color: lime;">; Time to run simulation for.</span><br /> (t0 0.0)<span style="color: lime;">; Starting time for simulation.</span><br /> (upwind 0.5)<span style="color: lime;">; Upwinding parameter [0 = only upstream, 1 = only downstream]</span><br /> p0<span style="color: lime;">; Initial road density for each cell.</span><br /> pin)<span style="color: lime;">; Input density function (veh/m). Should take one argument - the time.</span><br /> <span style="color: #b45f06;">#M{<br /> dx = roadLength/(n-1)</span><span style="color: lime;">; Spacing between cell centres.</span><span style="color: #b45f06;"><br /> pin = if pin pin fn(_) pj/4.0</span></span></span><br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"><span style="color: #b45f06;"><span style="color: #38761d;"> <span style="color: lime;">;</span></span></span></span></span><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"><span style="color: #b45f06;"><span style="color: lime;"><span style="font-family: "Courier New",Courier,monospace;">; Set the boundary density in the initial state.</span></span><br /> unless(p0 p0 := makeArray(n :initialElement 0.0) p0[0] := #!pin(t0))<br /> v(p) = vf*(1-p/pj)<span style="color: lime;">; Velocity as function of density.</span><br /> x(i) = (i-1)*dx<span style="color: lime;">; Cell centroid locations.</span><br /> xp(i) = if i<n (i-0.5)*dx roadLength<span style="color: lime;">; Plus, or right (downstream) boundary locations.</span><br /> xm(i) = if i>1 (i-1.5)*dx 0<span style="color: lime;">; Minus, or left (upstream) boundary locations.</span><br /> stepsim(pold atime dt) =<br /> makeVector(n fn(i) {<br /> pm = if i>1 (1-upwind)*pold[i-2]+upwind*pold[i-1] pold[0]<br /> pp = if i<n (1-upwind)*pold[i-1]+upwind*pold[i] pold[n-1]<br /> in = max(0 dt*pm*v(pm))<br /> out= max(0 dt*pp*v(pp))<br /> if i==1 #!pin(atime) pold[i-1] + (in - out)/(xp(i)-xm(i))})<br /> #L</span>(loop for atime from t0 to (+ t0 time-run) by dt<br /> for ps = p0 then (stepsim ps atime dt)<br /> do (loop for p across ps<br /> do (format t " ~4,1,3F" p)<br /> finally (terpri)))<span style="color: #b45f06;">}</span>)</span></span>Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-52185906242758615572013-01-26T13:52:00.000-08:002013-01-26T13:52:00.133-08:00Biblical Topic: ResurrectionThese are some notes I've put together about the resurrection and the immortality of the soul. All of the quotes are from the ESV unless otherwise noted, but please
have a Bible ready to look verses up in, because I have not included the
text of every quote. For many people, considering this may not be easy, but we know from
Proverbs 25:2 that "<i>It is the glory of God to conceal things, but the glory of kings is to search things out.</i>" Jesus also, knowing God, did the same and spoke in parables.<br />
<br />
Having said that, if you will listen further, here are some things to consider:<br />
<br />
Why did Martha say what she did, after Lazarus died?<br />
<br />
<div style="margin-left: 40px;">
<b>John 11:23-26:</b> <i>Jesus said to her, "Your brother will rise again." Martha said to him, "I know that he will rise again in the <span class="il">resurrection</span> on the last day." Jesus said to her, "I am the <span class="il">resurrection</span>
and the life. Whoever believes in me, though he die, yet shall he live,
and everyone who lives and believes in me shall never die. Do you
believe this?"</i></div>
<br />
There is a <span class="il">resurrection</span>, at the last
day. Jesus' comfort to her is not that he is still alive, but in heaven, but that he will rise again. Even though Lazarus died, <i>"yet shall he live"</i>. And,
everyone who lives and believes in Jesus shall never die - the Bible
tells us about God's and Jesus' understanding of that here:<br />
<br />
<div style="margin-left: 40px;">
<b>Matthew 22:31-32:</b> <i>And as for the <span class="il">resurrection</span>
of the dead, have you not read what was said to you by God: 'I am the
God of Abraham, and the God of Isaac, and the God of Jacob'? He is not
God of the dead, but of the living."</i></div>
<br />
By Jesus' words, we know that when God said that He is the God of Abraham, Isaac and Jacob, He was referring to the <span class="il">resurrection</span>
of the dead. So we understand God's power - he remembers them (Abraham,
Isaac and Jacob), and will raise them up on the last day. The <span class="il">resurrection</span>
is a key Bible theme and worthy of study. If this all seems
strange, perhaps Acts 17:30-32 will be reassuring. For further places to
look, read of <span style="background-color: #ff9900;"><span style="background-color: white;">Abraham sacrificing Isaac in Genesis 22:1-18, taking note of verses 5 and 10 and comparing with Hebrews 11:17-19</span></span>, and please read 1 Corinthians 15:12-<b>19</b>-23 - however the whole chapter is worth close study, especially about the <span class="il">resurrection</span>. Also, a Bible search on "<span class="il">resurrection</span>" will show many matches and will give a feel for the subject in the New Testament.<br />
<br />
The Old Testament is not silent on this subject, indeed, it helps us understand the <span class="il">resurrection</span>. One of the key areas are the promises to Abraham. For example:<br />
<br />
<div style="margin-left: 40px;">
<b>Genesis 13:14-17:</b> <i>The
LORD said to Abram, after Lot had separated from him, "Lift up your
eyes and look from the place where you are, northward and southward and
eastward and westward, for all the land that you see <span style="color: #000099;">I will give to you and to your offspring forever</span>.
I will make your offspring as the dust of the earth, so that if one can
count the dust of the earth, your offspring also can be counted.
Arise, walk through the length and the breadth of the land, for I will
give it to you."</i></div>
<br />
So we see that God promises two things: eternal life for
Abraham and his offspring, and a location to have eternal life in - he
and his descendants will have the land forever. Indeed, not just the
land of Israel, but ALL of the earth will be filled with the glory of
the Lord (Numbers 14:21, Habakkuk 2:14). By the Habakkuk quote, it is
people that fill the earth with God's glory. All of us, <span class="il">resurrected</span>
believers, in Christ, sinless, worshiping God and glorifying Him. I
would not say that is the only place we will ever go once we are <span class="il">resurrected</span> (it will not be a jail), but we will be immortal, and be given the land. Our Lord, Christ will reign over the world forever:<br />
<br />
<div style="margin-left: 40px;">
<b>Revelation 11:15:</b> <i>Then the
seventh angel blew his trumpet, and there were loud voices in heaven,
saying, "The kingdom of the world has become the kingdom of our Lord and
of his Christ, and he shall reign forever and ever."</i></div>
and<br />
<div style="margin-left: 40px;">
<b>2 Samuel 7:12-13:</b> <i>When
your days are fulfilled and you lie down with your fathers, I will
raise up your offspring after you, who shall come from your body, and I
will establish his kingdom. He shall build a house for my name, and I
will establish the throne of his kingdom forever.</i></div>
and<br />
<div style="margin-left: 40px;">
<b>1 Chronicles 17:9-14:</b> <i>And
I will appoint a place for my people Israel and will plant them, that
they may dwell in their own place and be disturbed no more. And violent
men shall waste them no more, as formerly, from the time that I
appointed judges over my people Israel. And I will subdue all your
enemies. Moreover, I declare to you that the LORD will build you a
house. When your days are fulfilled to walk with your fathers, I will
raise up your offspring after you, one of your own sons, and I will
establish his kingdom. He shall build a house for me, and I will
establish his throne forever. I will be to him a father, and he shall
be to me a son. I will not take my steadfast love from him, as I took it
from him who was before you, but I will confirm him in my house and in
my kingdom forever, and his throne shall be established forever.'"</i></div>
and<br />
<div style="margin-left: 40px;">
<b>Isaiah 9:7:</b> <i>Of the
increase of his government and of peace there will be no end, on the
throne of David and over his kingdom, to establish it and to uphold it
with justice and with righteousness from this time forth and
forevermore. The zeal of the LORD of hosts will do this.</i></div>
<br />
<br />
What then of our soul? We have been promised a <span class="il">resurrection</span> - why are we given a body to live immortally when <span class="il">resurrected</span>, as it says in 1 Corinthians 15:35-55? <br />
<br />
<div style="margin-left: 40px;">
<b>Romans 6:23:</b> <i>For the wages of sin is death, but the free gift of God is eternal life in Christ Jesus our Lord.</i></div>
<br />
Here we see the two options put before us. God has
given you and me the gift of eternal life - living forever. We will live forever, but sinners will not - they are <i>not</i> given the gift of eternal life, and, they will die. The two preceding verses emphasise the same point:<br />
<br />
<div style="margin-left: 40px;">
<b>Romans 6:21-22:</b> <i>But what fruit
were you getting at that time from the things of which you are now
ashamed? For the end of those things is death. But now that you have
been set free from sin and have become slaves of God, the fruit you get
leads to sanctification and its end, eternal life.</i></div>
<br />
So why are the wages of sin death? It started in Eden:<br />
<br />
<div style="margin-left: 40px;">
<b>Genesis 2:16-17:</b><i>
And the LORD God commanded the man, saying, "You may surely eat of
every tree of the garden, but of the tree of the knowledge of good and
evil you shall not eat, for in the day that you eat of it you shall
surely die."</i></div>
<br />
We know from the Bible record, that Adam and Eve did not die
that exact day - so what does verse 17 mean? The Hebrew in verse 17 for
"shall surely die" is "mooth mooth" - two H4191's. H4191 is Strong's
number for it. Strong says:<br />
<br />
<div style="margin-left: 40px;">
<b>H4191</b><br />
מוּת<br />
mûth<br />
mooth<br />
A
primitive root; to die (literally or figuratively); causatively to
kill: - X at all, X crying, (be) dead (body, man, one), (put to, worthy
of) death, destroy (-er), (cause to, be like to, must) die, kill, necro
[-mancer], X must needs, slay, X surely, X very suddenly, X in [no]
wise.</div>
<br />
The Hebrew word carries with it the meanings of death, kill,
destroy, slay, suddenly, in no wise. So to "die die" emphasises that
they would definitely die, be destroyed, surely and suddenly be no more.
So in that day that they ate that fruit, Adam and Eve were destined to
die and be no more.<br />
<br />
<div style="margin-left: 40px;">
<b>Genesis 2:7:</b><i> then the LORD
God formed the man of dust from the ground and breathed into his
nostrils the breath of life, and the man became a living creature.</i></div>
<br />
We came from the dust, and had life breathed into us. We were formed by God.<br />
<br />
<div style="margin-left: 40px;">
<b>Genesis 3:19:</b><i> By the sweat
of your face you shall eat bread, till you return to the ground, for out
of it you were taken; for you are dust, and to dust you shall return."</i></div>
<br />
We are dust, and to dust we return (see also Psalms 37:20;
49:12; 68:2). In a similar way, we, humans, are likened to grass that
grows up, but perishes away quickly (Psalms 103:14-16; 37:2, Isaiah
40:6-8; 37:27, James 1:10, but also see Matthew 6:30). We were formed
and given life by God, and He is who we should fear/respect and obey.
Our souls, our lives are God's:<br />
<br />
<div style="margin-left: 40px;">
<b>Ezekiel 18:4:</b> <i>Behold, all souls are mine; the soul of the father as well as the soul of the son is mine: the soul who sins shall die.</i></div>
<div style="margin-left: 40px;">
<b>Ezekiel 18:20: </b><i>The soul who sins shall die. The son shall not
suffer for the iniquity of the father, nor the father suffer for the
iniquity of the son. The righteousness of the righteous shall be upon
himself, and the wickedness of the wicked shall be upon himself.</i> </div>
<br />
Indeed, God has no pleasure in a person's death (Ezekiel 18:23,
Matthew 18:14) - even if they are wicked - God wishes us to obey Him and
live. The soul will die - another way to look at it is given in Genesis
6:3, where it says God's Spirit will not abide in man forever:<br />
<br />
<div style="margin-left: 40px;">
<b>Genesis 6:3:</b> <i>Then the LORD said, "My Spirit shall not abide in man forever, for he is flesh: his days shall be 120 years."</i></div>
<br />
Without
God we are nothing - he sustains everything by His power, so when
someone dies, and God's Spirit leaves them. When we die, go to Sheol,
return to dust, we will not think, or know, or
do anything:<br />
<br />
<div style="margin-left: 40px;">
<b>Ecclesiastes 9:10:</b> <i>Whatever
your hand finds to do, do it with your might, for there is no work or
thought or knowledge or wisdom in Sheol, to which you are going.</i></div>
<br />
This is not an isolated quote; see also Psalms 112:9-10,
Proverbs 10:28; 11:7. So, what is the result of all this? Even though we
are weak and in many ways insignificant, we respect and love the God
that loved us before we loved Him, and thank Him for His gift towards us
of eternal life through His son, Jesus Christ, and obey Him - not from
fear - but from respect and gratitude for all He has done for us.<br />
<br />
For further reading, see Revelation 20:12-14, where we read of the
book of life, and how the sea, death and hades/hell give up the dead in
them, and they are judged. Why would hades/hell grouped with the sea, and death?<br />
<br />
So I ask again, why did Martha say <i>"I know that he will rise again in the <span class="il">resurrection</span> on the last day."</i>, and not something else?Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com1tag:blogger.com,1999:blog-1798883676384076486.post-36684677848964418662013-01-19T22:32:00.000-08:002013-01-19T22:32:00.584-08:00Random Scripts in Various LanguagesIn the last few weeks of work, I've come across several different languages to perform different tasks. They were useful, so I've included them below.<br />
<br />
<h2>
PowerShell</h2>
The first one is <a href="http://technet.microsoft.com/en-us/library/bb978526.aspx">PowerShell</a>. We used it to extract data for a customer. It's a temporary measure - their business intelligence server will be able to do this for them soon. The idea was to automate calling some SQL queries on a server and exporting the results as <a href="http://en.wikipedia.org/wiki/Comma-separated_values">CSV</a>. Of interest is that I set the culture to get a specific datetime format (I know, I could get the same effect in SQL). Here is some cleansed parts of the script:<br />
<br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">$startDate = "11 Oct 2012"<br />$da<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">ys = "1"</span></span></span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">$prefix = "declare @StartDate datetime, @EndDate datetime<br />set @StartDate = DATEADD(HH, -10, '$startDate')<br />set @EndDate = DATEADD(DD, $days, @StartDate)"<br /><br />$culture = [System.Globalization.CultureInfo]::InvariantCulture.Clone()<br />$culture.DateTimeFormat.ShortDatePattern = "yyyy-MM-dd"<br />$culture.DateTimeFormat.LongTimePattern = "HH:mm"<br />[System.Threading.Thread]::CurrentThread.CurrentUICulture = $culture<br />[System.Threading.Thread]::CurrentThread.CurrentCulture = $culture</span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;"><br /></span></span>
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">Write-Output "Extract $days day(s) worth of data from ${startDate}:"</span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;"><br /></span></span>
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">Write-Host "Extracting Performance Log data..."<br />$query = "$prefix<br /><br />select Column_Names etc."</span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">.....</span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">$data = Custom-Call-SQL $query</span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">Write-Host "Exporting CSV file..."<br />$data | Export-CSV PerformanceData.csv -encoding ascii -notype</span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">.....</span></span><br />
<br />
To run a PowerShell script, put it in a file named something like "script.ps1", open a Powershell prompt (should be under Accessories in the Start menu), and enter the script file and path.<br />
<br />
<h2>
AutoHotkey</h2>
The next one was an unusual (to me) use for <a href="http://www.autohotkey.com/">AutoHotkey</a>. I say unusual, because I didn't think AutoHotkey would be great at working with large files, but it was. It combines the <i>whole</i> contents of several files from sub-folders "Day 2" to "Day 7" into one master file. The reason I went to AutoHotkey is that the files were too big for Notepad++. Here is the script:<br />
<br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">#NoEnv<br />#SingleInstance force<br />SendMode Input<br />SetWorkingDir %A_ScriptDir%<br /><br />OutputFile = PerformanceData.csv<br />Loop, 6<br />{<br /> Day := A_Index+1<br /> From = Day %Day%\%OutputFile%<br /> CombineLines(From, OutputFile)<br />}<br />MsgBox, Finished copying content to %OutputFile%.<br />Return<br /><br />CombineLines(fromfile, tofile)<br />{</span></span><br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;"> ;; The "to" file is open for the whole loop for efficiency when done this way.</span> Loop, Read, %fromfile%, %tofile%<br /> {<br /> FileAppend, %A_LoopReadLine%`n<br /> }<br />}</span></span><br />
<br />
To run an AutoHotkey script like this one, copy the contents into a file like "script.ahk" and double click it (assuming you have AutoHotkey installed).<br />
<br />
<h2>
Unix Find and Grep</h2>
The next one is from my friend Michael Gleeson. It's a Unix command, and it searches the files in a directory for the <span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;"><string></span></span>, and prints the file and matching line to standard output. It is:<br />
<br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">find . -type f -print0 | xargs -0 grep <string></span></span><br />
<br />
<h2>
Regular Expressions</h2>
The second last one is for (<a href="http://www.pcre.org/">Perl compatible</a>) regular expressions. <a href="http://notepad-plus-plus.org/">Notepad++</a> was updated to use Perl compatible regular expressions as of <a href="http://notepad-plus-plus.org/news/notepad-6.0-release.html">version 6</a>. Notepad++ can use regular expressions for "Find and Replace". Doing so is a great feature - it gives you great flexibility to not only find bits of text that match specific patterns, but to also intelligently rearrange or replace those bits of text. I used it recently to change date formats in some of the files I generated with the above scripts. The find text was "(\d{2})/(\d{2})/(\d{4})", and the replace text was "\2-\1-\3". The parentheses in the find text create variables you can use in the replacement text. In our case, we have created three variables. They are named \1, \2 and \3. In the replace text, I've swapped the variables around, because I am converting American Month-Day-Year format to an Australian Day-Month-Year format.<br />
<br />
<br />
Performing a find and replace in Notepad++ with the above terms replaces "02/27/1900" with "27-02-1900", etc.<br />
<br />
See also <a href="http://markantoniou.blogspot.com.au/2008/06/notepad-how-to-use-regular-expressions.html">a post on Mark's Speechblog</a> for more on Notepad++'s powerful find and replace (pre version 6). Also, I'm told that a Unix command, sed (stream editor) can do similar things, and a lot more (see <a href="http://www.grymoire.com/Unix/Sed.html">here for a great page about sed</a>).<br />
<br />
<h2>
Visual Basic</h2>
<br />
The last one is from Visual Basic. I use this in an Excel file, to find a single file. It opens a standard file selector dialog. It's a function, so you call it when you want a file. The function returns a Boolean indicating whether a file was successfully selected, and it puts the file name into the ByRef argument. Here it is:<br />
<br />
<span style="color: #741b47;"><span style="font-family: "Courier New",Courier,monospace;">Function GetAFileName(ByRef FileName As String) As Boolean<br /><span style="color: #38761d;">' Actually browse for a file to import.</span><br /> Dim fd As FileDialog<br /> Set fd = Application.FileDialog(msoFileDialogOpen)<br /> fd.AllowMultiSelect = False<br /> GetAFileName = (fd.Show = -1)<br /> If GetAFileName Then<br /> FileName = fd.SelectedItems(1)<br /> End If<br /> Set fd = Nothing<br />End Function</span></span><br />
<br />
Have you got any random scripts of your own? Please share them below.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-3601246701847066692013-01-12T13:54:00.000-08:002013-01-12T13:54:00.157-08:00Ignoring Arguments in Anonymous FunctionsAnonymous functions are a useful (hmm, that's an understatement) feature of Common Lisp. I use them a lot. While using them, sometimes I want to ignore some arguments that are required by the consumer of the anonymous function. For example, here is an example of collecting the keys in a hash-table into a list:<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(let (result)<br /> (maphash <span style="color: #38761d;">(lambda (key value)<br /> (declare (ignore value))<br /> (push key result))</span><br /> hash-table)</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> result)</span></span><br />
In this situation, the anonymous function is quite simple, and the ignore advice is swamping it. I wrote a small macro (named <span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">fn</span></span>) to make ignoring arguments in anonymous functions easier. It's included and used extensively in the <a href="http://metalightnet.blogspot.com/2012/09/mathp-math-notation-in-common-lisp.html">MathP</a> code. To ignore an argument, use an underscore for it in the argument list. For example, the above code becomes:<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(let (result)<br /> (maphash <span style="color: #38761d;">(fn (key _) (push key result))</span></span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> hash-table)</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> result)</span></span><br />
Because the code is that much shorter, I find it that much easier to read. Here is the macro that does the magic:<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(defmacro fn (args &body body)<br /> (let (arg-list ignores)<br /> (loop for arg in args<br /> if (string= (symbol-name arg) "_")<br /> do (let ((sym (gensym)))<br /> </span><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: "Courier New",Courier,monospace;">(push sym arg-list) </span>(push sym ignores))<br /> else do (push arg arg-list))<br /> `(lambda ,(nreverse arg-list) (declare (ignore ,@ignores)) ,@body)))</span></span><br />
I hope the above code is useful to you; Use it however you want. I accept no responsibility
for problems arising from it's use, but if you do find it useful, I'd be
tickled pink to hear from you.<br />
<br />
Do you know of a similar macro? Please leave a comment.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com2tag:blogger.com,1999:blog-1798883676384076486.post-37710483728297236272013-01-05T16:08:00.000-08:002013-01-05T16:08:00.139-08:00Syntax for Lambda-Lift/Positional-LambdaI've checked out the clever <a href="http://www.hexstreamsoft.com/projects/lambda-lift/">Lambda-Lift library</a> <a href="https://github.com/Hexstream/lambda-lift">by Hexstream</a>, and I like it. It's a library that provides a succinct way to write positional lambdas. Having recently used implemented a reader macro, I decided to try one out for it. Almost immediately afterwards, I read <a href="http://www.reddit.com/r/lisp/comments/zr3xq/new_library_lambdalift_is_a_concise_intuitive_and/">the Reddit announcement</a>, which mentioned that not using a reader macro was a good idea.<br />
<br />
It seems that wanting to use reader macros for small things is a common weakness in Common Lisp programmers. Uses of dispatching macro character pairs to shorten code can actually make the code harder to read. This is more likely for people who don't know what the associated dispatch function does (or even sometimes where it came from). The tendency towards reader macros may arise from the desire for a more concise way to write Lisp code. This may be more of an issue if you are used to writing very terse code, such as Perl of Mathematica.<br />
<br />
The issue with reader macros for general consumption is that they provide another layer to understand. While definitely not insurmountable, effort is still required to investigate and understand what the reader macro does or produces. In effect, reader macros use syntax to compress Lisp code.<br />
<br />
The most Lispy way to compress code is probably to use higher order functions and macros. I think the benefit of using macros is that building macros upon macros is easier because of the uniform syntax. When macros are the right choice, you can benefit from their rich support in Common Lisp.<br />
<br />
Anyway, here's my attempt. Use or leave it.<br />
<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(defun read-positional-lambda-form (stream char n)<br /> (declare (ignore char))<br /> (let* ((next (peek-char nil stream))<br /> (n (or n (and (digit-char-p next)<br /> (- (char-code (read-char stream))</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> #.(char-code #\0)))))<br /> (next (peek-char nil stream))<br /> (rest (and (char-equal next #\r) next))<br /> (next (progn (when rest (read-char stream))</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> (peek-char nil stream)))<br /> (body (if (member next '(#\Space #\Tab #\Newline nil #\)))<br /> '() `(,(read stream nil nil t)))))<br /> `(lambda-lift:lift ,@(when n `(,(intern (format nil "~D" n) '#:keyword)))<br /> ,@(when rest `(&rest ,(read-from-string (string rest))))<br /> ,@body)))<br /><br />(set-dispatch-macro-character #\# #\L #'read-positional-lambda-form)</span></span><br />
<br />
The above code is released into the Public Domain the same as the <a href="http://www.hexstreamsoft.com/projects/lambda-lift/">Lambda-Lift library</a>. Here are some examples of it:<br />
<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">'#L3 <span style="color: #38761d;">;== (lift :3)</span><br />'#L3(print :2) <span style="color: #38761d;">;== (lift :3 (print :2))</span><br />'#L2r <span style="color: #38761d;">;== (lift :2 &rest r)</span><br />'#L3r(print r) <span style="color: #38761d;">;== (lift :3 &rest r (print r))</span><br />'#L3:2 <span style="color: #38761d;">;== (lift :3 :2)</span><br />'#L2rr <span style="color: #38761d;">;== (lift :2 &rest r r)</span><br />(funcall #L5 </span></span><span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span>'one 'two 'three 'four 'five)<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #38761d;">;== FIVE</span></span></span></span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(funcall #L5:3 'one 'two 'three 'four 'five)<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #38761d;">;== THREE</span></span></span></span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(funcall #L5(string :1) 'one 'two 'three 'four 'five)<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #38761d;">;== "ONE"</span></span></span></span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(funcall #L5(reverse (string :4)) 'one 'two 'three 'four 'five)</span></span><span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #38761d;">;== "RUOF"</span></span></span></span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(funcall #L2rr 'one 'two 'three 'four 'five)<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #38761d;">;== (THREE FOUR FIVE)</span></span></span></span></span>Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-43426936169202089212012-12-29T04:58:00.000-08:002012-12-29T04:58:00.068-08:00An Alternative Traffic Speed-Density RelationshipPreviously we've examined <a href="http://blog.metalight.net/2012/12/macroscopic-model-of-traffic.html">a macroscopic traffic model</a>, which contained, as one of its model equations, a relationship between speed and density. That relationship is reproduced here:<br />
$$v = v_f (1 - \rho/\rho_j),$$ where<br />
\(v\) = vehicle speed (m/s);<br />
\(v_f\) = free flow speed (m/s);<br />
\(\rho\) = vehicular density (veh/m); and<br />
\(\rho_j\) = jam density (veh/m), the average vehicles per metre in stationary traffic.<br />
<br />
Here I present an alternative speed-density relationship based on headways. Headway is the spacing between vehicles, usually as a time, but it can also be expressed in terms of distance.<br />
<br />
In addition to expressing the above headway concepts, the new speed equation should satisfy two conditions. At zero density, the speed should be \(v_f\), and at the jam density, the speed should be zero.<br />
<br />
But first we will develop the headway concept. As stated above, headway is usually expressed as a time. That's a good starting point. If we denote temporal headway as \(h_t\) (s/veh), then we may write that: $$h_t = 1/q = 1/\rho v,$$ or rearranged: $$v = 1/\rho h_t.$$ There is a difficulty with that relationship because at the jam density, the speed is still non-zero. However, note that \(1/\rho\) is the distance per vehicle. If we replace \(1/\rho\) with \(1/\rho-1/\rho_j\), then the equation becomes: $$v = \frac{1}{h_t}(1/\rho-1/\rho_j),$$ and the speed at the jam density is zero.<br />
<br />
The only issue left with the above equation is that the speed is undefined at zero density, instead of being \(v_f\). To overcome this and ensure that the speed is \(v_f\) at zero density, I've developed this equation: $$v = \frac{1}{\frac{1}{v_f} + \frac{h_t}{(1/\rho-1/\rho_j)}}.$$ Unfortunately it still suffers from being undefined at zero density, but it's now more easily overcome. The final formula for speed is: $$v = \frac{1}{\frac{1}{v_f} + \frac{h_t\rho}{(1-\rho/\rho_j)}}.$$<br />
<br />
We have previously <a href="http://blog.metalight.net/2012/12/analysis-of-speed-density-flow.html">analysed the original flow-density relationship</a>, and we will do similar here. Thanks the the equation \(q=\rho v\), in this alternative formulation, flow is given by: $$q = \frac{\rho}{\frac{1}{v_f} + \frac{h_t\rho}{(1-\rho/\rho_j)}}.$$<br />
The analysis to determine capacity for this relationship is more involved, but definitely solvable. The critical density is given by: $$\rho_c = \frac{1-\sqrt{h_t v_f \rho_j}}{1/\rho_j - v_f h_t}.$$ Capacity may be calculated by using the critical density in the flow equation above. The relationships are displayed in this graph for \(\rho_j\) = 1/7 veh/m and \(h_t\) = 0.7 s/veh:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgklwewWN0JaAnfUjb3syvcXoUrBUGymj0JWeM5ngkOw0IMMM0pMcfdXjVR9wPw5OY36tgxM7uIP_47Qgj6BlBPNja5UJiqYIT2x9JL_zLNlOfto3ozs8Y7dW2jfjQwK__bqpqPoCX8o24/s1600/Alternative+Flow-Density+Relationship.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="" border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgklwewWN0JaAnfUjb3syvcXoUrBUGymj0JWeM5ngkOw0IMMM0pMcfdXjVR9wPw5OY36tgxM7uIP_47Qgj6BlBPNja5UJiqYIT2x9JL_zLNlOfto3ozs8Y7dW2jfjQwK__bqpqPoCX8o24/s400/Alternative+Flow-Density+Relationship.png" title="Alternative Flow-Density Relationship" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">An alternative flow-density relationship based on headways.</td></tr>
</tbody></table>
<br />
Interestingly, the original flow-density relationship is approximately recovered when \(h_t\) = 1/4 s/veh. That is encouraging, and means that this alternative speed-density relationship might be considered as a generalisation of <a href="http://blog.metalight.net/2012/12/analysis-of-speed-density-flow.html">the original one</a>. But why is it the specific value of \(h_t\) = 1/4 s/veh? Well, after some rearranging of the final speed formula above, we can write it as: $$v = \frac{v_f (1-\rho/\rho_j)}{1+\rho(h_t v_f - 1/\rho_j)}.$$ The top part happens to be equal to our original speed equation, so to make them completely equal, we just have to satisfy \(h_t v_f = 1/\rho_j\). Finally, if \(v_f\) = 27.78 m/s (100 km/h), and \(\rho_j\) = 1/7 veh/m, then \(h_t\) should be 0.252 s. No wonder a headway of 0.25 s appeared to give the original speed-density relationship.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-3210777045632463612012-12-22T20:53:00.000-08:002012-12-22T20:53:00.540-08:00Discretising Base Traffic Model EquationsThis post is a followup of <a href="http://blog.metalight.net/2012/12/macroscopic-model-of-traffic.html">these earlier</a> <a href="http://blog.metalight.net/2012/12/analysis-of-speed-density-flow.html">posts</a>. Here we discretise the traffic model equations to let us solve them numerically. Here are the model equations (including boundary conditions) all together in one place:<br />
$$q = \rho v,$$ $$\frac{\partial \rho}{\partial t} + \frac{\partial q}{\partial x} = S(x,t),$$ $$v=v_f ( 1 - \rho/\rho_j ),$$ $$S(x,t) = 0,$$ $$\rho(x,0) = 0,$$ and $$\rho(0,t) = \rho_j/4.$$ where<br />
\(q\) = traffic flow rate (veh/s) past the point;<br />
\(\rho\) = vehicular density (veh/m);<br />
\(v\) = vehicle speed (m/s);<br />
\(\partial\) indicates partial differentiation;<br />
\(t\) = time (s);<br />
\(x\) = distance (m) along road;<br />
\(S\) = vehicles entering (+ve) or leaving (-ve) the road (veh/m/hr);<br />
\(v_f\) = free flow speed (m/s); and<br />
\(\rho_j\) = jam density (veh/m), the average vehicles per metre in stationary traffic.<br />
<br />
Note that we've set \(S(x,t)\) to zero. This means that no vehicles are leaving or entering the road apart from at the ends.<br />
<br />
The presence of the very simple equation for flow, \(q\), means that we can eliminate flow from the equations altogether. When a value for flow is needed, we can just multiply density and speed together. As we progress, we may (or may not) find it desirable to do the same with speed. With flow removed, the main equation becomes: $$\frac{\partial \rho}{\partial t} + \frac{\partial \rho v}{\partial x} = S(x,t).$$ My favourite discretisation method is to <a href="http://www.cfd-online.com/Wiki/Finite_volume">use control volumes - the finite volume method</a>. The first step is to divide the domain into cells, or control volumes. Here is how we will do that:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPjYB8QVwYPPAZBBwy38h10CVzDdKaz7oMABFuvclD2IdBIqz6B-IAYPfN54tgKUpwUKdPpt9VCS_6IRmfUDMg5x2OuGgvAvjr9U2dAv4OB1WppkqzQ2xU96T4PgVFzLtzuKaJ3hgRjlM/s1600/Discretisation+Grid.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="33" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjPjYB8QVwYPPAZBBwy38h10CVzDdKaz7oMABFuvclD2IdBIqz6B-IAYPfN54tgKUpwUKdPpt9VCS_6IRmfUDMg5x2OuGgvAvjr9U2dAv4OB1WppkqzQ2xU96T4PgVFzLtzuKaJ3hgRjlM/s320/Discretisation+Grid.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Discretisation grid for our traffic equations, showing coordinates for cells 1, <i>i</i> and <i>n</i>.</td></tr>
</tbody></table>
where a trailing minus sign indicates the left boundary, and a trailing plus sign indicates the right boundary. Because the right boundary of one cell is the left boundary of the next cell, we have \(x_{i+} = x_{i+1-}\). Dots indicate the location used to calculate representative model values contents for each cell.<br />
<br />
There is also a time dimension, and we'll refer to the current time with \(t_c\), the target, or future, time with \(t_f\). The time step of our discretisation is given by \(t_f - t_c = \Delta t\). <br />
<br />
We will discretise our density equation by integrating it over the volume of each cell, 1 to \(n\). Since we have two dimension, \(x\) and \(t\), the integration over the volume involves two integrals.<br />
<h2>
Body Cells: 2 to <i>n</i>-1</h2>
First we'll integrate over space: $$\int_{x_{i-}}^{x_{i+}}\frac{\partial \rho}{\partial t}\,dx + \int_{x_{i-}}^{x_{i+}}\frac{\partial \rho v}{\partial x}\,dx = 0.$$ The first integral is approximated using the <a href="http://en.wikipedia.org/wiki/Rectangle_rule">rectangle rule</a> with one rectangle using the midpoint approximation (\(x=x_i\)). The second integral simplifies thanks to the <a href="http://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus">fundamental theorem of calculus</a>. Applying those (and explicitly writing the function arguments for \(\rho\) and \(v\)), we get: $$(x_{i+}-x_{i-}) \frac{\partial \rho(x_i,t)}{\partial t} + \left[\rho(x,t) v(x,t)\right]_{x_{i-}}^{x_{i+}} = 0.$$ Now we'll apply the time integral from the current time, \(t_c\), to the future time, \(t_f\). For the second integral, we use the <a href="http://en.wikipedia.org/wiki/Rectangle_rule">rectangle rule</a>, with top left corner approximation (\(t=t_c\)): $$(x_{i+}-x_{i-}) \left[\rho(x_i,t)\right]_{t_c}^{t_f} + (t_f-t_c) \left[\rho(x,t_c) v(x,t_c)\right]_{x_{i-}}^{x_{i+}} = 0.$$ Next, we rearrange it to have the density at the future time on the left, and everything else on the right: $$\rho(x_i,t_f) = \rho(x_i,t_c) - \frac{t_f-t_c}{x_{i+}-x_{i-}}\left(\rho(x_{i+},t_c) v(x_{i+},t_c) - \rho(x_{i-},t_c) v(x_{i-},t_c)\right).$$<br />
<h2>
Left Boundary Cell: 1</h2>
The left boundary equation doesn't need to be obtained by integrating as it is given by the existing boundary condition: $$\rho(0,t) = \rho_j/4.$$<br />
<h2>
Right Boundary Cell: <i>n</i></h2>
For the right boundary cell, we can reuse the equation from the body cells, but updated to refer to the last cell's coordinates (\(i\rightarrow n, x_{i+}\rightarrow x_{n}\)): $$\rho(x_n,t_f) = \rho(x_n,t_c) - \frac{t_f-t_c}{x_n-x_{n-}}\left(\rho(x_n,t_c) v(x_n,t_c) - \rho(x_{n-},t_c) v(x_{n-},t_c)\right).$$<br />
<br />
The next step in this thread will be solving these discretised equations.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-16281214690362969032012-12-15T21:58:00.000-08:002012-12-15T21:58:00.046-08:00Smooth Minimum and MaximumThe functions we examine in this post are closely related to <a href="http://en.wikipedia.org/wiki/P-norm#The_p-norm_in_finite_dimensions">p-norms</a>. Lets say we have two equations that describe aspects of a relationship. For example, we might describe the selling price of an item in terms of a discounted price, \(d\), for small purchases, and a lower bound price, \(u\), for bulk purchases. In that case, we might have two equations to describe price: $$d(x)=202-2x,$$ and $$u(x)=150,$$ where \(x\) is the number of units purchased in a single transaction. In this case, it might be fine to simply decide the selling price, \(p\) as $$p(x) = \max(d(x), u(x)),$$ but what if we want a formula for the selling price that has continuous derivatives? (<a href="http://en.wikipedia.org/wiki/Smooth_function">i.e. is smooth</a>) Well, the formula I found in an attempt to do this is: $$m(x, s) = (d(x)^s + u(x)^s)^{1/s},$$ where \(s\) is the 'strength' of the maximisation.<br />
<br />
The above formula is basically a p-norm (and is the <a href="http://en.wikipedia.org/wiki/Euclidean_norm#Euclidean_norm">Euclidean norm</a> when \(s\) = 2). Here's a chart of it in action on \(d\) and \(u\) with \(s\) set to 2, 4, 6 and 8: <br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixiF7OWnE9CSzuHm8_-tmRIiz4NDn5Nm-z_8kkhFOlz9BLoKxm7dJ7IP8b5RZPpiPcBAk4fGT4yTm1uYleyiy4mLKfmjsaPcTzSezGocuIfXjMmCLdIXhPeptCTptSrBz2SZYlniHX1bc/s1600/Smooth+Maximum+Pricing.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixiF7OWnE9CSzuHm8_-tmRIiz4NDn5Nm-z_8kkhFOlz9BLoKxm7dJ7IP8b5RZPpiPcBAk4fGT4yTm1uYleyiy4mLKfmjsaPcTzSezGocuIfXjMmCLdIXhPeptCTptSrBz2SZYlniHX1bc/s400/Smooth+Maximum+Pricing.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Example of a smooth maximum function for combining formulas.</td></tr>
</tbody></table>
The chart shows that a higher strength, \(s\) leads to a 'tighter' maximum. In the limit as \(s\) goes to infinity, we actually obtain the plain \(\max\) function. But what happens at higher unit quantities? Specifically, what happens when one of our inputs is negative? Well, that's shown here:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVr0LQqQ80qAx5oOWP6-LMthYLJDUB7aKhWtJ_lfMX0PW4J3zEQG7t7jl19fohOGeKJQ7VV5U9UXNRvV7-l9dLkjfS3pGA-2_AIa8UP_p0077mQw07DE8h6jIKcbHGmiSXe8D691Zy0aU/s1600/Smooth+Maximum+Negative.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhVr0LQqQ80qAx5oOWP6-LMthYLJDUB7aKhWtJ_lfMX0PW4J3zEQG7t7jl19fohOGeKJQ7VV5U9UXNRvV7-l9dLkjfS3pGA-2_AIa8UP_p0077mQw07DE8h6jIKcbHGmiSXe8D691Zy0aU/s400/Smooth+Maximum+Negative.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Example of the effect of a negative input on the smooth maximum.</td></tr>
</tbody></table>
<br />
That's not so good. The even strengths stay above both inputs, but diverge further and further above the intended maximum. The odd strengths (only one shown) start to trend towards the negative input, because towards the right, it is the largest in absolute value.<br />
<br />
Before we attempt to deal with this issue, let's look at another interesting behaviour. Let's consider negative strengths. This chart shows strengths of -2, -3, -4 and -5:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzH9l88UlIcPJPm5sEYjMhgPBclXHVN9UOA7l2r1S96ZpyaFiyil5aOqdbrxf_JMOhb8sCVGt_GcsGp-wN5REynv1ePGZmcbX52rLXFGEhEJQSdJ2DPiV06ufmqJUGiUZ2qPSrf6pLOmM/s1600/Smooth+Minimum+Pricing.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgzH9l88UlIcPJPm5sEYjMhgPBclXHVN9UOA7l2r1S96ZpyaFiyil5aOqdbrxf_JMOhb8sCVGt_GcsGp-wN5REynv1ePGZmcbX52rLXFGEhEJQSdJ2DPiV06ufmqJUGiUZ2qPSrf6pLOmM/s400/Smooth+Minimum+Pricing.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A negative strength produces a smooth minimum function!</td></tr>
</tbody></table>
<br />
That's a convenient way to take the continuous minimum! And what happens when we feed in negative inputs? Well, it gets a little crazy:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8ro_GsZA7CtfndinbWmTfByYhVkw0wNaeAY8pabyQKbnU9V0tWZ5v9KApcJ_K_5z3yn8gpyifo5C3jrlVMb6tLg0DSJTiLkICnGtSNpw0jFDn1poqfqtF0-qFn6tkGS5wzMQE3DHaMc0/s1600/Smooth+Minimum+Negative.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi8ro_GsZA7CtfndinbWmTfByYhVkw0wNaeAY8pabyQKbnU9V0tWZ5v9KApcJ_K_5z3yn8gpyifo5C3jrlVMb6tLg0DSJTiLkICnGtSNpw0jFDn1poqfqtF0-qFn6tkGS5wzMQE3DHaMc0/s400/Smooth+Minimum+Negative.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A smooth minimum of a negative input does not look pretty.</td></tr>
</tbody></table>
<br />
So then, how might we deal with negative inputs? One way would be to transform inputs from the full number line onto just the positive half. To do that we turn to exponentiation. So here's the updated continuous maximum/minimum function, generalised to any number of functions: $$m(x, s) = \ln_b\left(\left[ \sum_{i=1}^q (b^{f_i(x)})^s \right]^{1/s}\right),$$ where \(b\) is the base of exponentiation. So, let's test it. I initially tried \(w = e\), but ran into overflow issues, and instead have used the value 1.01. Here is the maximum and minimum of positive and negative inputs, with \(s\) being 2, 5, -2 and -5:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6fGTPzfZmniMfp1jUf7aknDCWk7j_0SZP0Qu7FZoKn-xALxsr887jZK2FhFPL3qzs0mtpAjIaMubQyA4hBVRlOEV9EQPWRXL-OUbkY7MEg9UBAHo43vWxJr9HLdBVoaXdyICd8-2BMs4/s1600/Smooth+Min-Max+Robust.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6fGTPzfZmniMfp1jUf7aknDCWk7j_0SZP0Qu7FZoKn-xALxsr887jZK2FhFPL3qzs0mtpAjIaMubQyA4hBVRlOEV9EQPWRXL-OUbkY7MEg9UBAHo43vWxJr9HLdBVoaXdyICd8-2BMs4/s400/Smooth+Min-Max+Robust.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">A smooth minimum and maximum function that works with negative inputs.</td></tr>
</tbody></table>
<br />
One final thing. To use this in Lisp on individual values, evaluate this (with <a href="http://blog.metalight.net/2012/09/mathp-math-notation-in-common-lisp.html">MathP</a>):<br />
<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(defun smooth-min-max (b s &rest vals)</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"> <span style="color: #990000;">"Smooth minimum (s < -1) or maximum"</span><br /> <span style="color: #38761d;">#M log(reduce{#'+ vals :key fn(v) (b^v)^s}^(1/s) b)</span>)</span></span><br />
<br />
And to construct a function that minimises or maximises other functions, try something like this:<br />
<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">(defun smooth-min-max-lambda (b s &rest funcs)<br /> <span style="color: #990000;">"Returns a function that calculates a smooth min/max of the</span></span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #990000;">given base and strength. If b > 1, positive s does maximisation,</span></span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #990000;">negative s minimisation. If 0 < b < 1, it is reversed."</span><br /> (assert (or (< 0 b 1) (> b 1)))<br /> (assert (not (zerop s)))<br /> <span style="color: #38761d;">#M fn(&rest args) log(reduce(#'+ funcs :key fn(f) (b^apply(f args))^s)^(1/s) b)</span>)</span></span><br />
<br />
Enjoy!Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com4tag:blogger.com,1999:blog-1798883676384076486.post-12408230249505255362012-12-08T14:12:00.000-08:002012-12-08T14:12:00.446-08:00Analysis of Speed Density Flow RelationshipThese notes have been inspired by a recent paper by Rahman,
Ben-Edigbe and Hassan*. In it they analyse the speed, density and flow relationship.<br />
<br />
The equations given in <a href="http://blog.metalight.net/2012/12/macroscopic-model-of-traffic.html">this previous traffic modeling post</a> include an algebraic relationship between speed, density and flow: $$q=\rho v$$ and $$v = v_f(1-\rho/\rho_j),$$ where<br />
\(q\) = flow rate (veh/s);<br />
\(\rho\) = vehicle density (veh/m);<br />
\(v\) = vehicle speed (m/s);<br />
\(v_f\) = free flow speed (m/s), nominally 27.78 m/s;<br />
\(\rho_j\) = jam density (veh/m), nominally 1/7 veh/m.<br />
<br />
Given the above equations, it is possible to eliminate \(v\). That is, flow can be expressed in
terms of density by using the speed equation:<br />
$$q=v_f\rho ( 1 - \rho/\rho_j ).$$ This is a quadratic, and it has a maximum. Because it's a quadratic, this means that <a href="http://en.wikipedia.org/wiki/Multivalued_function">the inverse relationship is not a function, as it's multi-valued</a>
(one flow rate may be associated with two densities). Here is a graph of the flow-density relationship with the nominal values:<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP5x3fCd-Kdo2AKfIP3b1tU9wfmNuSRqCDGGs2jfYe66RWPUL6MK42xXpzEGZ0EuPjK7N7i4QTZVxMSWZ3NVYnH1Gr3em0DukfXSA33ZBibIfkQC7-h1AQJ34VSJwMuqlUW1Nt6O1I9CU/s1600/Flow-Density+Relationship.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img alt="Flow is a function of density. At 0 density, flow is zero. As density increases, flow increases to a maximum (called capacity), then decreases, eventually reaching 0 when the density is the jam density." border="0" height="302" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgP5x3fCd-Kdo2AKfIP3b1tU9wfmNuSRqCDGGs2jfYe66RWPUL6MK42xXpzEGZ0EuPjK7N7i4QTZVxMSWZ3NVYnH1Gr3em0DukfXSA33ZBibIfkQC7-h1AQJ34VSJwMuqlUW1Nt6O1I9CU/s400/Flow-Density+Relationship.png" title="Flow-Density Relationship" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Relationship between flow and density, showing key values.</td></tr>
</tbody></table>
<br />
The maximum point
on the flow curve happens to be the capacity of the roadway. We find
the maximum point by differentiating the above and solving for slope
equals zero. The critical density, \(\rho_c\) (the density at which the
flow rate equals capacity), is found to be \(\rho_j/2\), and the
capacity, \(q_c\), is given by:<br />
$$q_c=v_f\rho_j/4.$$ With the
values mentioned above (\(v_f\) = 27.78 and \(\rho_j\) = 1/7), the
capacity is 0.99 veh/s, which while high, is in the right order of
magnitude for freeways (which I think is around 0.5 to 0.7 veh/s).<br />
<br />
The next post on this topic will be <a href="http://blog.metalight.net/2012/12/discretising-base-traffic-model.html">model discretisation</a>.<br />
<br />
*
The paper is Rahman, R., Den-Edigbe, J. E., and Hassan A. (2012), Extent of
Traffic Shockwave Velocity Propagations Induced by U-Turn Facility on
Roadway Segments. <i>25th ARRB Conference</i>. Mentioned <a href="https://s3-ap-southeast-1.amazonaws.com/ap-southeast-1.accounts.ivvy.com/account1501/events/1445/files/5046ec2dd3fe4.pdf">here</a>.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-48340347838997379122012-12-01T20:49:00.000-08:002012-12-01T20:49:00.120-08:00Macroscopic Model of TrafficI work in the Intelligent Transport Systems (ITS) industry, at <a href="http://www.transmax.com.au/">Transmax</a>, and completed a PhD in applied mathematics at <a href="http://www.qut.edu.au/">QUT</a>. So it should come as no surprise that I want to combine and explore the two areas. To combine my two interests, I have investigated <a href="http://en.wikipedia.org/wiki/Macroscopic_traffic_flow_model">macroscopic models of traffic flow</a>.<br />
<br />
This post presents a simple model of traffic flow. It will form the baseline for further work and modifications. I learned of these equations from <a href="http://econpapers.repec.org/article/eeetransb/v_3a22_3ay_3a1988_3ai_3a6_3ap_3a421-435.htm">this paper</a> by Paul Ross, published in 1988.<br />
<br />
<h2>
Model Equations</h2>
The first equation comes from the definitions of flow, density and speed:<br />
<div style="text-align: left;">
$$q = \rho v,$$ where</div>
\(q\) = traffic flow rate (veh/s) past the point;<br />
\(\rho\) = vehicular density (veh/m); and<br />
\(v\) = vehicle speed (m/s).<br />
<br />
The above equation states that the number of vehicles that will pass by a point is equal to the density of traffic at that point times the speed of vehicles at that point. That is, flow rate increases with density and speed.<br />
<br />
The second <a href="http://en.wikipedia.org/wiki/Partial_differential_equation">(partial differential) equation</a> was given by Lighthill and Whitham in 1955. It describes the conservation of vehicles:<br />
$$\frac{\partial \rho}{\partial t} + \frac{\partial q}{\partial x} = S(x,t),$$ where<br />
\(\partial\) indicates <a href="http://en.wikipedia.org/wiki/Partial_derivative">partial differentiation</a>;<br />
\(t\) = time (s);<br />
\(x\) = distance (m) along road; and<br />
\(S\) = vehicles entering (+ve) or leaving (-ve) the road (veh/m/hr).<br />
<br />
The third equation describes vehicle speed. The simplest relationship would have to be linear relationship between speed and density, as reported by Greenshields in 1934. This speed equation gives a free flow speed at zero density, and zero speed at the jam density:<br />
$$v=v_f ( 1 - \rho/\rho_j )$$ where<br />
\(v_f\) = free flow speed (m/s); and<br />
\(\rho_j\) = jam density (veh/m), the average vehicles per metre in stationary traffic.<br />
<br />
Let's say that the free flow speed is 100km/h. That means \(v_f = 27.78\) m/s. Also, let's assume that the average vehicle length is 5 metres, and that in a jam, they are spaced 2 metres apart. That means \(\rho_j = 1/7\) veh/m.<br />
<br />
The equation for speed has an important effect on the traffic in the simulation, and has received a lot of attention in the literature. Various forms have been presented in the literature, and we will look at some of them in the future.<br />
<br />
<h2>
Boundary Conditions</h2>
A model with a partial differential equation is not complete without boundary conditions. There are a few options for us, but we must specify two boundary conditions - one for a point in space, and one for a point in time. First, some notation to help us specify the boundary conditions. We will refer to flow, density and speed as functions of two variables by writing \(q(x,t)\), \(\rho(x,t)\) and \(v(x,t)\).<br />
<br />
Before we actually specify the boundary conditions, note that we have one partial differential equation, and two algebraic equations. With the two algebraic equations we can translate density to/from speed, and calculate flow from density or speed (but not the reverse - we'll see why below).<br />
<br />
The time condition is usually chosen to be for time zero. We might choose that initially:<br />
$$\rho(x,0) = 0$$ for all \(x\). In this model, it is equivalent to specifying \(v(x,0) = v_f\).<br />
<br />
For this model, the space condition can be specified in terms of density or speed, as we can use the equations to determine the unspecified measures. Let's choose:<br />
$$\rho(0,t) = \rho_j/4.$$ I don't think it's very important, but let's say that this condition overrides the time condition at \(x=t=0\).<br />
<br />
In the future we may change the space condition to be a function of time, for example:<br />
$$\rho(0,t) = \frac{(1+sin(2\pi t/T))}{2}\frac{\rho_j}{4}.$$<br />
<br />
<h2>
What's Next?</h2>
In another post we will <a href="http://blog.metalight.net/2012/12/analysis-of-speed-density-flow.html">analyse the relationship between speed, density and flow</a>. After that we'll <a href="http://blog.metalight.net/2012/10/discretising-base-traffic-model.html">discretise the model equations so we can solve them numerically</a>. And after that we may investigate the effect of different speed equations on model behaviour.<br />
<br />
P.S. Thanks to <a href="http://www.mathjax.org/">MathJax</a> and <a href="http://mytechmemo.blogspot.com.au/">My technical memo</a> for <a href="http://mytechmemo.blogspot.com.au/2012/02/how-to-write-math-formulas-in-blogger.html">the script to render equations</a>.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-48845007157195950342012-11-24T17:12:00.000-08:002012-11-24T17:12:00.296-08:00Window PeelerI've said before that <a href="http://www.autohotkey.com/">AutoHotkey</a> <a href="http://blog.metalight.net/2012/09/if-you-use-windows-please-use-autohotkey.html">is a great program that every Windows users should have and use</a>. Here's yet another use I found for it to make my (and yours) life easier. Have you ever had two full-screen windows on the same monitor and wanted to switch between them quickly? I encounter that situation regularly. With two or three monitors, I use one in portrait orientation for email and viewing documents, and the others for everything else. To switch between windows, the Task Bar, Alt+Tab and Windows+Tab are great, but when I have 20+ windows open, it can take a fair bit of fiddling and time to switch between email and documents on the same monitor. I wanted a better solution. So I wrote this script (<a href="https://dl.dropbox.com/u/58518258/AHK/Window%20Peeler.ahk">download</a>):<br />
<br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;"><span style="color: #38761d;">;;;; Window Peeler - Show next window under mouse pointer</span><br />#NoEnv <span style="color: #38761d;">;; Standard prelude</span><br />#SingleInstance force<br />SendMode Input</span></span><br />
<span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">SetWorkingDir %A_ScriptDir%<br /><br /><span style="color: #38761d;">;; Pick one of your mouse buttons (XButton1 = Back, XButton2 = Forward, MButton = middle button, LButton = left button, etc.) and use it here:</span><br />XButton1::<br /> MouseGetPos,,, WinId<br /> WinSet, Bottom,, ahk_id %WinId%<br /> <span style="color: #38761d;">;MouseGetPos,,, WinId</span><br /> <span style="color: #38761d;">;WinActivate, ahk_id %WinId%</span><br />Return</span></span><br />
<br />
It moves the window under the cursor to the back when the back button is pressed on your mouse (assuming you have that button). That leaves the next window down on top! The two commented out lines of code activate that window, but I like it without that because it makes the script run quicker. It's a very simple script.<br />
<br />
To make it trigger on another combination, for example Control+RightMouseButton, replace <span style="color: #b45f06;"><span style="font-family: "Courier New",Courier,monospace;">XButton1::</span></span> with <span style="font-family: "Courier New",Courier,monospace;"><span style="color: #b45f06;">^RButton::</span></span> (<span style="font-family: "Courier New",Courier,monospace;"><span style="color: #b45f06;">^</span></span> is for Control).<br />
<br />
P.S. Note that mouse software may interfere with the Back and Forward mouse button events. In the Logitech software, I had to set the action for that button to <i>Other: Generic Button</i>.<br />
<br />
What do you think? Please leave a comment.Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com0tag:blogger.com,1999:blog-1798883676384076486.post-54695786844933269982012-11-17T22:48:00.000-08:002012-11-17T22:48:00.621-08:00MathP is not CL Standards CompliantBad news! <a href="http://blog.metalight.net/2012/09/mathp-math-notation-in-common-lisp.html">MathP</a>, my very own mathematics notation library for Common Lisp, breaks the <a href="http://webstore.ansi.org/RecordDetail.aspx?sku=ANSI+INCITS+226-1994+%28R2004%29#.UKHlmYbTVYs">ANSI CL standard</a>. The problem is that <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_unrd_c.htm">unread-char</a> cannot be called consecutively without calling something that will read a character (like <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_cha.htm#read-char">read-char</a>). From the CL Hyperspec page for <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_unrd_c.htm">unread-char</a>:<br />
<blockquote class="tr_bq">
It is an error to invoke <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_unrd_c.htm#unread-char" rel="DEFINITION"><b>unread-char</b></a> twice consecutively on the same <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_s.htm#stream" rel="DEFINITION"><i>stream</i></a> without an intervening call to <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_cha.htm#read-char" rel="DEFINITION"><b>read-char</b></a> (or some other input operation which implicitly reads characters) on that <a href="http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_s.htm#stream" rel="DEFINITION"><i>stream</i></a>. </blockquote>
<br />
I used it to basically peek multiple characters ahead, like <a href="http://www.lispworks.com/documentation/HyperSpec/Body/f_peek_c.htm#peek-char">peek-char</a>, but for multiple characters. This may be why MathP doesn't work in CLISP. That allows me to have arbitrary operators. For example, I <i>could </i>have the following as distinct operators:<br />
<ul>
<li>* for multiplication</li>
<li>** (perhaps for exponentiation)</li>
<li>.* (perhaps for element-wise multiplication, like in <a href="http://www.mathworks.com.au/products/matlab/">MATLAB</a>)</li>
<li>*. (dot product?)</li>
<li>*.* (perhaps for element-wise exponentiation)</li>
<li>etc.</li>
</ul>
<br />
I thought I was being clever, but such a use contravenes the standard pretty clearly. So I'm interested in alternatives. Does anyone know if it's possible to do multiple unread-chars with other stream implementations? Also, can you read lisp from them with standard reading functions?Anonymoushttp://www.blogger.com/profile/12242792031255007733noreply@blogger.com2