tag:blogger.com,1999:blog-46863930504076858652017-09-10T12:07:04.239-07:00The ScholarFeaturing many interesting topics in one place, including politics, philosophy, logic, math, comedy, music, and literature.Daniel Haskinnoreply@blogger.comBlogger25125blogspot/FaFWUhttps://feedburner.google.comtag:blogger.com,1999:blog-4686393050407685865.post-77338675842679393482017-08-05T13:05:00.003-07:002017-08-05T13:06:25.845-07:00On Package Manager Architectures, Part II am sort of a package manager junky. I even wrote my own package manager, capable of managing dependencies across programming language boundaries, called <a href="https://degasolv.readthedocs.io/">Degasolv</a>. During the course of my travels, I've noticed some very significant things about package management architecture.<br /><br />There are really three different kinds of package managers. Each fundamental type of package manager makes trade-offs. Each type is fairly successful in its own ecosystem. It is instructive to point out the differences.<br /><br />Here I will treat the two most significant. The third type deserves its own blog post (assuming I get to it). For the curious, it includes <a href="https://en.wikipedia.org/wiki/Apache_Ivy">ivy</a> and <a href="https://maven.apache.org/">maven</a>, and I will discuss this one later.<br /><br /><h3>The Main Differences</h3><br />The first type is that of the system package manager. The archetype of this category is <a href="https://fedoraproject.org/wiki/Yum">YUM</a>, and more recently, <a href="https://fedoraproject.org/wiki/DNF?rd=Dnf">DNF</a>. In this model, the following facts are true:<br /><br /><ol><li>Packages install files into a shared file system, and are shared resources. Only one package of each package name may exist in an installation at any given time. Packages may NOT share ownership of a particular file (RPM is actually pretty strict about this), and generally do not share resources. </li><li>Because of this, there must be agreement on package semantics. Since the "libc" package is a shared resource, all packages must agree on what "libc" means. This means that all packages must agree on an acceptable version of libc.</li><li>All packages are owned by the system, NOT by other packages. Java apps do not specify how to configure Java, for example. The systems administrator is in charge of configuring the Java package, not other packages that rely on Java.</li><li>No domain knowledge exists at the package level of the "type" of thing being installed; all DNF knows about are files. Packages installing a C shared library and packages installing a tomcat service are in some sense created equal.</li><li>At at least a theoretical level, circular dependencies are possible. It is possible to resolve the dependency of "a -> b -> a", by installing both "a" and "b". </li></ol><div>Contrast this with a manager like <a href="https://www.npmjs.com/">NPM</a>. NPM is the archetypal package manager of the second type of package managers, a class which I will call the "hierarchical package managers". Others include <a href="https://github.com/whyrusleeping/gx">GX</a> and <a href="https://helm.sh/">Helm</a>. It is very popular, and very different:</div><div><ol><li>All packages are installed relative to the package requiring them. Therefore, packages are not shared resources. Package installations are only used by the package that depends on them. There are no shared resources anywhere (in theory); if A relies on B, it is the only package relying on B. If, for example, package A relies on both B and C, and package B relies on package C, then package B will get its own copy of C installed relative to B and package A will get its own copy of C installed relative to A. A and B do not share C at all.</li><li>Because of this, no agreement on package semantics is necessary. A and B in the example above do not need to agree on what "C" means; A can use 2.0 of package C and B can use 1.0 of package C and no one cares.</li><li>In this sense, packages are "owned" by parent packages. This can be seen in this category of package manager with the Helm pacakge manager. Values in the sub-packages' values.yaml (the package's configuration file) may be overridden by values in a parent package. Ownership, the sort of "care and feeding" that the depended on package needs to work, is provided by the depending package.</li><li>The package manager takes advantage heavily of domain knowledge. It makes assumptions about what is being installed and only makes sense in the context of some programming language or system, such as Javascript in NPM's case or Kubernetes in Helm's case.</li><li>Because packages are installed relative to the packages that rely on them, circular dependencies are not possible</li></ol><h3>On Shared Resources</h3><div>The most interesting point in the above discussion, in my opinion, is that of whether or not a package is a shared resource. Consider <a href="https://github.com/kubernetes/helm/issues/2762">this bug I filed with the Helm chart package manager</a>. In it, I show that although the package manager Helm is of the second type, and therefore assumes that packages (in Helm nomenclature, "charts") are not shared resources, this is not always the case. In the default case, packages create services using names that assume that there exists only one package of a certain name in any given release. </div></div><div><br /></div><div>In short, in order for a package manager to be of the second type, and for that to work, packages must truly and in every way must not be shared resources, ever. There are subtle corner cases in every language or system where this is simply not true. </div><div><br /></div><div>Consider the example of two packages with a "mutual friend" package. In this scenario, Package Alice and Package Ben have a mutual friend, Package Cat. Alice talks to Cat and asks Cat to tell her the right amount of money needed to buy a horse. Alice then asks Ben to buy a horse for her, giving him needed money. Ben then asks Cat if the money given to buy the horse is enough.</div><div><br />The above example is contrived and tells the story of the classic diamond: Package A, which relies on Package B and Package C. Package B also relies on Package C.</div><div><br /></div><div>Now consider if these packages were NPM packages. Package B's Package C is installed relative to B, and could be at an entirely different version than Package A's Package C. This version difference is perhaps breaking. So, what may end up happening is that Package Alice asks Cat how much money to use for buying a horse, and Cat's methods of figuring out how much money that is may have completely changed between Cat 2.0 and Cat 3.0 . So Alice's Cat 2.0 says she needs $1000, and she gives this to Ben. Ben asks Cat 3.0 if that's enough, but Cat 3.0 says "no". Now Ben gives an error and no one knows why.</div><div><br /></div><div>This example shows that even though Ben and Alice do not share the same Cat package, they are sharing her as a resource. They rely on her expertise and believe that whatever Cat says is right. Therefore NPM's fundamental assumption that Cat is not a shared resource is violated. The developers of Alice don't talk to Ben's developers, but they're both in the same community and both have been told to use package Cat for all things horse. It's simply the de facto solution in the community.</div><div><br /></div><div>Though contrived, this is a real problem. NPM tried to fix this by introducing "<a href="https://blog.domenic.me/peer-dependencies/">peerDependencies</a>" for those packages where this really matters, and I think this isn't a bad plan. It allows packages to use the hierarchical method of managing dependencies, assuming packages aren't shared resources, for the general case, while allowing them to specify hard requirements when problems arise.</div><h3>On Ownership</h3><div>A second fundamental difference between these is ownership. I'm now considering the differences between RPM, a package from the systems family, and Helm charts, packages from the hierarchical family. I do this because charts are unique (as far as I can tell) because <a href="https://docs.helm.sh/chart_template_guide/#subcharts-and-global-values">you can configure them using their values.yaml file from a parent chart</a>. This means that in some sense depending packages in helm can configure their depended on packages.</div><div><br />Contrast this with RPM. A Java app like <a href="https://jenkins.io/">Jenkins</a> installed <a href="https://pkg.jenkins.io/redhat/">via RPM</a> would never presume to configure Java for you. Things like Java heap size are entirely up to the administrator. A central authority emerges in this model, where the sysadmin or <<a href="https://saltstack.com/">insert</a> <a href="https://www.ansible.com/">favorite</a> <a href="https://en.wikipedia.org/wiki/Infrastructure_as_Code">infrastructure-as-code</a> <a href="https://puppet.com/">tool</a> <a href="https://www.chef.io/">here</a>> tool is responsible for configuring the package and making it work.</div><h3>Which is Better?</h3><div>I think this boils down to a discussion around where the authority should be. Should packages be made to share resources owned by a central authority (the sysadmin), or should they be given their own sandbox, allowed to use what's in their box with no regard to the needs of other packages?</div><div><br /></div><div>This has a direct corollary question to human communities and how communication takes place, <a href="https://wingolog.org/archives/2015/11/09/embracing-conways-law">as it must</a>. Should developer teams coordinate, often centrally? Or, should we try to isolate developer teams so that they do not need to coordinate or communicate?</div><div><br /></div><div>This question sounds harsh, but do and must ask and answer this question all the time. It is everywhere. This is particularly true in DevOps, which is my profession. Do we make two teams' products share a virtual machine when we deploy their code, or do they get separate VMs? We usually choose the latter isolating them from each other. Do we make two teams' products agree on what version of PostgreSQL to use, though they will use separate databases? Yes; our support contract only supports certain versions of this backing, depended-on service. Both teams depend on the database admins, and the database admins's service won't work with theirs unless certain constraints are met.</div><div><br /></div><div>So: as a package manager designer, which one do we choose? Do we enforce some coordination between packages? If we do, all packages will agree on semantics (e.g., package "B" will mean the same thing to all depending packages, because it will be the same version). All packages will need some central authority to configure them. If we don't, packages could be allowed to configure sub-packages, depending in turn on configuration given to them. Do we trust package authors to make the right configuration choices? They may be trustworthy, but will have no knowledge of other packages within the same installation. Will this cause problems? </div><img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/nJk3h8MnmBs" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2017/08/on-package-management-strategy.htmltag:blogger.com,1999:blog-4686393050407685865.post-89998026599019906102016-06-22T22:13:00.004-07:002016-06-23T10:51:25.978-07:00Modeling Recursive Sum Types in C++11 Using boost::variantIt's been a while. But here's something cool.<br /><br />I used to <b>love</b> pattern matching with sum types in OCaml in college. But I <b>also</b>love how useful and ubiquitous C++ is. So I wanted pattern matching and sum types, but in C++. Well, people say boost::variant can be used as a sum type. The library boost::variant is fairly ubiquitous, well-maintained, and can even run on C++98, the older C++ standard. I can see how discriminated unions can implement “flat” sum types, but can it be used to implement <b>recursive</b>sum types?<br /><br />Well, I decided to try it. It turns out, with a bit of scaffolding on my part, I was able to implement a recursive sum type. I tried to model the quintessential recursive type, the natural number, which is either zero or the successor to some other number. The following code shows the results of my efforts.<br /><br /><pre>// sum_type.cpp<br />#include <iostream><br />#include <boost/variant.hpp><br />#include <memory><br /><br />struct zero {};<br />class successor;<br /><br />typedef boost::variant<zero,successor> number;<br /><br />class successor<br />{<br />private:<br /> std::unique_ptr<const number> num;<br />public:<br /> successor() = delete;<br /> successor(const number& n) : num(new number(n)) {}<br /> successor(const successor& s) : num(new number(s.n())) {}<br /> successor(successor&& s) : num(std::move(s.num)) {}<br /><br /> const number& n() const {<br /> return *num;<br /> }<br />};<br /><br />struct match_count : public boost::static_visitor<int><br />{<br /> int operator ()(const zero& z) const<br /> {<br /> return 0;<br /> }<br /> int operator ()(const successor& s) const<br /> {<br /> // Do NOT use `return (*this)(s.n()) + 1`<br /> return boost::apply_visitor(*this, s.n()) + 1;<br /> }<br />};<br /><br />number add(const number& a, const number& b)<br />{<br /> /*<br /> match a with<br /> 0 => b<br /> S n => S add(n, b)<br /> */<br /> struct match_a : public boost::static_visitor<number><br /> {<br /> const number b;<br /> match_a(const number& b) : b(b) {}<br /> number operator()(const zero& a) const<br /> {<br /> return b;<br /> }<br /> number operator()(const successor& a) const<br /> {<br /> return successor(add(a.n(), b));<br /> }<br /> };<br /> return boost::apply_visitor(match_a(b), a);<br />}<br /><br />int main() {<br /> number a = zero();<br /> number b = successor(a);<br /> number c = successor(b);<br /> number d = add(b,c);<br /> match_count mc;<br /> int c_count = boost::apply_visitor(mc, c);<br /> int b_count = boost::apply_visitor(mc, b);<br /> int a_count = boost::apply_visitor(mc, a);<br /> int added = boost::apply_visitor(mc, d);<br /> std::cout << "a is " << a_count << std::endl;<br /> std::cout << "b is " << b_count << std::endl;<br /> std::cout << "c is " << c_count << std::endl;<br /> std::cout << "a + b is " << added << std::endl;<br />}<br /></number></pre><br />Output:<br /><br /><pre>[ djhaskin987@djhaskin987-S301LA:~ ]$ g++ -o sum_type -std=c++11 sum_type.cpp<br />[ djhaskin987@djhaskin987-S301LA:~ ]$ ./sum_type<br />a is 0<br />b is 1<br />c is 2<br />a + b is 3<br /></pre>How about that?<br />I modelled the type as a discriminated union between “zero” and “successor”. Some interesting things I learned when I did this, or at least some things to note: <br /><ul><li>As long as you manage memory properly in the recursive cases, they work fine as part of the sum type using boost::variant.</li><li>It’s okay to have a type with no members (e.g. <tt>struct zero {};</tt>)</li><li>You can define anonymous classes inside function definitions. Here, they aren’t anonymous, but experimentation will show that you can (in C++11).</li><li> You can call functions recursively when you define structs inside those functions. That’s nice.</li><li>When defining “matching” structs inside functions, try to match variable names with class member names that they are used to construct. This saves time later reasoning about what’s going on.</li></ul><img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/cxk_SUrA1Hk" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2016/06/modeling-recursive-sum-types-in-c11.htmltag:blogger.com,1999:blog-4686393050407685865.post-50880874837206201462014-12-03T21:12:00.002-08:002014-12-03T21:12:34.969-08:00svopt<div class="post-content"><h2 class="title"></h2><div class="body-text">The optimization algorithm “vopt” applied to any optimization problem is simple. I now outline my own version, which I call “s-vopt” because it “swings” from one level of opt local search to another.<br /><ol><li>Convert your solution representation to a bit array.</li><li>Go through each bit, flip it, and see if it improves the solution. If it does, keep the bit flipped and repeat until there are no more bits that can be flipped to reach a local maxima (assuming you’re maximizing a fitness function). You have now reached a local 1-opt maxima.</li><li>Now flip each possible pair of bits, flip them, and see if the fitness rating improves. if it does, keep those bits flipped and go to step 2. If all the pairs have been tried without success continue to the next step.</li><li>Continue in this fashing, first trying to flip all possible triples, then quadruples, then quintuples, etc. until you want to stop. At each, if an improved solution is found, keep it and go to step 2. if not, continue on the next step.</li></ol>Happy Mountain Climbing!<br /><br /><img src="http://media.tumblr.com/0ba2bb74755baaf5c7c88b09a96fb713/tumblr_inline_nfpcimYY2A1saws7v.png" /></div></div><img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/FfEyPle4ZtE" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2014/12/svopt.htmltag:blogger.com,1999:blog-4686393050407685865.post-2319000321359826692014-02-12T10:20:00.001-08:002014-02-12T13:08:01.014-08:00"Brent": the Story of the Volunteer Warrior, and The Mayhem That EnsuedIf you haven't read <a href="http://www.amazon.com/Phoenix-Project-DevOps-Helping-Business-ebook/dp/B00AZRBLHO/ref=sr_1_1?ie=UTF8&qid=1392229179&sr=8-1&keywords=the+phoenix+project">The Phoenix Project</a>, I gotta tell ya, it's a good book (even though there is some language in it, admittedly true to life in many IT organizations). In there is a story of an engineer called Brent. Brent is crucial for most IT operations of any kind. Every thing he knows is in only his head, and documented nowhere. If anything is to get done, Brent needs to be involved.<br /><br />A real time-bomb situation.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://www.mariowiki.com/images/thumb/6/63/BobombNSMBU.png/200px-BobombNSMBU.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://www.mariowiki.com/images/thumb/6/63/BobombNSMBU.png/200px-BobombNSMBU.png" /></a></div><br /><br />The book goes on to talk about how to diffuse this time bomb, but it doesn't talk about how to prevent it in the first place.<br /><br /><h2>The Perfect Storm for Brent</h2><br />This happened because of the "Volunteer Viscous Cycle". It happens when the dispatching of problems to engineers to fix them happens on a volunteer basis.<br /><br />The following diagram shows, in essence, what happens in the volunteer workflow:<br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-_EkZEBwyUto/UvutD_fs1rI/AAAAAAAAAvc/w55VltT0RvA/s1600/Brent.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-_EkZEBwyUto/UvutD_fs1rI/AAAAAAAAAvc/w55VltT0RvA/s1600/Brent.png" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"></div><br />This is <i>exactly</i> what creates a Brent: an uncontrolled, volunteer-based dispatch system when problems arise. A team of engineers hesitant to jump in and help, and one volunteer, constitues a perfect storm for new Brents to form.<br /><br /><h3>The New Problem</h3><br /><br />When a new problem arises -- a bug, a ticket, or an issue, depending on your issue tracking system -- engineers on a team often hesitate to take it, given that they can choose what problems to take and what to fix. They are not hesitant to take the issue because they are lazy or dumb. They are most often well-educated, highly-trained, seasoned engineers; however, new problems, never seen before, still daunt these engineers. Any engineer who takes it will make lots of mistakes, become frustrated, and spend lots of time fixing it. Further, they could use the same time to fix 3 problems that they know how to fix. So, they wait and see if someone else will volunteer to take this particular problem.<br /><br />Enter Brent, a guy who just wants to get stuff done. He may be highly educated, or he may be just out of high school, but he has drive. He'll volunteer for anything, either because he's just trying to be helpful, or because he's trying to show that he is valuable, or simply because no one else will take the ticket. He's a first-rate volunteer, a real go-getter. And he's about to become a dumping ground for all sorts of problems.<br /><br /><br />Brent sees that others do not feel comfortable hacking at a problem and helpfully, proudly, or even meekly, volunteers. It takes him a while, but he eventually resolves the issue and everyone's happy.<br /><br />Brent starts taking on so many of these new issues that people just assume it's "Brent's job" or "Brent's niche" to take on new or unusual tasks, and so come to expect them picking up the slack.<br /><br /><br /><h3>The Returning Bug (Uh-Oh)</h3><h3> </h3><div class="separator" style="clear: both; text-align: center;"><a href="http://static1.fjcdn.com/comments/That+was+the+longest+++gif+I+ve+ever+seen+but+_ed02ba77425b32e71cbe491199ce4521.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://static1.fjcdn.com/comments/That+was+the+longest+++gif+I+ve+ever+seen+but+_ed02ba77425b32e71cbe491199ce4521.jpg" /></a></div><br /><br />Brent eventually takes on enough issues that a few of them reappear, or new issues appear which are related to older ones. This time, something in the server environment changed, which breaks a service that Brent has previously serviced. Everyone instantly sees this server is broken and remembers how hard Brent worked on this problem last time. They think that he'll be able to do it faster than themselves, and so it is assigned to him. He may even volunteer for to take the issue, trying to be helpful. Brent fixes it for the team. He learns even more about the server than he knew from the last time he fixed it. The problem is, others on his team know even less, because they stopped worrying about the server once the issue was given to Brent.<br /><br /><h3>The Silo Effect</h3><h3> </h3>A long time passes with this process in place. It is now too difficult for all of Brent's knowledge to be documented. There's simply too much to write it all down, and quite frankly, too many fires that Brent needs to fight. When problems arise that have to do with "Brent" servers, the only one that can fix them is Brent. He is now considered a "crucial resource". It is simply a waste of Brent's valuable time to document issues already fixed, when there are so many <i>current</i> issues that only he can fix. There simply isn't time. <br /><br /><h2>Diffusion</h2><i>The Phoenix Project</i> goes into some good detail about how to diffuse this situation. As a recap:<br /><ol><li>Limit Brent's work-in-process by using the <a href="http://www.kanbanblog.com/explained/">kanban process</a>.</li><li>Get engineers shadowing Brent.</li><li>Disallow Brent the keyboard. His shadows must do all the work.</li></ol><h2>Prevention</h2>In order to diffuse Brent, you must put mulitple shadow engineers on him, lest he quit and you end up with "just another Brent". <b>More than one engineer at a time must know how fix any given problem in their space of responsibility</b>, and hopefully in more than their region of responsibility.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-W1mzg9R6J38/Uvu_BuEcTOI/AAAAAAAAAvs/YAnHPcO1etA/s1600/TertiaryRedundance.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/-W1mzg9R6J38/Uvu_BuEcTOI/AAAAAAAAAvs/YAnHPcO1etA/s1600/TertiaryRedundance.png" height="222" width="400" /></a></div><br /><br />A great way to ensure this from the start to institute round-robin assignment of issues to members of the team. Rules:<br /><br /><ol><li>Issues are assigned to members of a team in a round-robin fashion. This way everyone knows about everything.</li><li>If an engineer needs help on an issue from another engineer, he may request that the engineer document the process and then send him a link to the wiki page, but the only the engineer assigned the ticket, issue, task, or subtask must actually do the work. This way, every thing currently worked on is currently documented. </li></ol>Rule 2 above is especially useful. If the wiki page is unclear, the author must clarify the wiki page so the engineer can do the work. If a particular engineer is called on to write multiple wiki pages, it is probably a sign that he has been a "Brent" in the past and so rule 2 naturally protects against such volunteer warriors. If everyone knows how to fix a particular issue, then the idea is that if a particular engineer needs help on that issue, he can ask the team, or otherwise a more or less random person. The main point is that the author or authors of the wiki page are asked to write it. This principle guards against volunteer warriors. <br /><br />Rule 1 may seem inefficient, since some engineers naturally find it easier to solve some problems than others. It is not meant to be efficient; rather, it endows <i>resilience</i> to a team. You'll never find an IT team with efficiency problems, but I have yet to find one without resiliency problems. Lots of IT professionals will brag about how many VMs they can manage, or how fast they can fix a problem, but those same IT techs will tell you horror stories about when something went down and Brent was on vacation. IT organizations who follow Rule 1 will find that the tradeoff between efficiency and resiliency is worth it. Bugs will be fixed slower, but they will always be fixable, come rain, shine, or even (gasp!) a sick Brent.<br /><br /><b>EDIT</b>: An earlier version of this article used "Brett" instead of "Brent". The character in The Phoenix Project is "Brent", so the name "Brett" in this article was changed to match the character, consistent with what I was trying to do on the first draft. <img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/JVGWcOU9rEs" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2014/02/brett-story-of-volunteer-warrior-and.htmltag:blogger.com,1999:blog-4686393050407685865.post-28393435933669968762014-01-16T18:59:00.001-08:002014-01-16T18:59:53.511-08:00ratpoison and xdotool: How to Move the Mouse by Using the Keyboard in LinuxWe interrupt this blog for an important announcement: With <a href="http://www.nongnu.org/ratpoison/">ratpoison</a>, you can use the mouse using keyboard bindings!<br /><br />For those of you who don't know what ratpoison is, it's a <a href="https://wiki.archlinux.org/index.php/Window_Manager">window manager </a>for linux, like <a href="http://fluxbox.org/">fluxbox</a>, <a href="http://www.gnome.org/">GNOME</a>, or <a href="http://www.kde.org/">KDE</a>. It's designed to be able to work without a mouse (hence the name). Using ratpoison, I have found a way to use the pointer without actually using the mouse.<br /><br />Here is my <code>.ratpoisonrc</code> file:<br /><pre>startup_message off<br />set font Mono-10<br />set bargravity nw<br />set bgcolor cyan<br />exec rpws -i<br />exec /usr/bin/rpws init 4 -k<br />source .ratpoisonkeys<br />source .ratpoisonmouse<br />set winname class<br /><br />set border 0<br /></pre><br />And here is my <code>.ratpoisonmouse</code> file:<br /><pre>bind C-j ratclick 1<br />bind C-k ratclick 2<br />bind C-l ratclick 3<br />definekey top M-j ratrelwarp 0 16<br />definekey top M-k ratrelwarp 0 -16<br />definekey top M-h ratrelwarp -16 0<br />definekey top M-l ratrelwarp 16 0<br />definekey top M-y ratrelwarp -16 -16<br />definekey top M-u ratrelwarp 16 -16<br />definekey top M-b ratrelwarp -16 16<br />definekey top M-n ratrelwarp 16 16<br /><br />definekey top M-J ratrelwarp 0 256<br />definekey top M-K ratrelwarp 0 -256<br />definekey top M-H ratrelwarp -256 0<br />definekey top M-L ratrelwarp 256 0<br />definekey top M-Y ratrelwarp -256 -256<br />definekey top M-U ratrelwarp 256 -256<br />definekey top M-B ratrelwarp -256 256<br />definekey top M-N ratrelwarp 256 256<br /><br />definekey top F10 ratclick 1<br />definekey top F11 ratclick 2<br />definekey top F12 ratclick 3<br />definekey top M-i rathold down 1<br />definekey top M-o rathold down 2<br />definekey top M-p rathold down 3<br />definekey top M-I rathold up 1<br />definekey top M-O rathold up 2<br />definekey top M-P rathold up 3<br /></pre><br />The entries in the above file mean that if I type ALT+H,J,K, or L, I can move the mouse left, down, up or right. F10 clicks on stuff, and F12 right-clicks on stuff. The rest can be extrapolated, I think, by looking at the .<code>ratpoisonmouse</code> file above.<br /><br />Don't wanna <a href="https://wiki.archlinux.org/index.php/Ratpoison">switch to ratpoison</a>? You can do the same thing in any other linux window manager using <a href="http://www.semicomplete.com/projects/xdotool/xdotool.xhtml">xdotool</a>. It's a commandline program that lets you move the mouse around, among other things. By binding keystrokes to different xdotool commands, you can get the mouse to move and click.<br /><br />For example, here is what could be an excerpt from <code>.fluxbox/keys</code>, the fluxbox keybindings file to do move the mouse up, down, left and right as explained above, plus click the mouse:<br /><br /><pre>Mod1 j :Exec "xdotool mousemove_relative -- 0 16"<br />Mod1 k :Exec "xdotool mousemove_relative -- 0 -16"<br />Mod1 h :Exec "xdotool mousemove_relative -- -16 0"<br />Mod1 l :Exec "xdotool mousemove_relative -- 16 0"<br />F10 :Exec "xdotool click 1"<br />F11 :Exec "xdotool click 2"<br />F12 :Exec "xdotool click 3"<br /></pre><br />Cool, huh?<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/BiFmEJ4ZwB8" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2014/01/ratpoison-and-xdotool-how-to-move-mouse.htmltag:blogger.com,1999:blog-4686393050407685865.post-7551727442961594052014-01-16T17:50:00.001-08:002014-01-16T18:38:50.798-08:00How to Comply With the NSA While Maintaining Privacy For Your Users<a href="http://mashable.com/2013/08/09/silent-circle-lavabit-shut-down-to-avoid-nsa-snooping/">Silent Circle and Lavabit closed their doors</a> because they didn't wish to give their user data to the NSA. This article describes how a web service can fairly easily store user data so that nobody--not even the hosting web service--could access private user data, except the user to whom the rightfully belongs. This can even be done while complying to the NSA. You can store metadata (the kind of data the NSA cares about) about a user unencrypted while still encrypting the user's address and telephone number fairly easily.<br /><h3> </h3><h3>Storing Private Data Securely </h3><br />First, let's go back in time to the <a href="http://arstechnica.com/tech-policy/2011/06/sony-hacked-yet-again-plaintext-passwords-posted/">Sony hack</a>. This was especially embarassing to Sony because they stored all their passwords in plain text. For those technically normal people out there, <a href="http://en.wikipedia.org/wiki/Cryptographic_hash_function">there is a way to create data based on a password called a <i>hash</i></a>, store that data, and then use that data later to check whether a user entered their password correctly or not by making another hash and check whether it matches the stored hash. It is fairly easy to store password hashes instead of the password itself, and it is far more secure to do so.<br /><br />Admittedley, it is a little more complicated than that. In order to thwart <a href="http://netsecurity.about.com/od/hackertools/a/Rainbow-Tables.htm">rainbow tables</a>, web site owners need to store a "<a href="https://crackstation.net/hashing-security.htm">salt</a>" (a large random number) for each user and then create a hash based on the salt and the password together. The bottom line, however, is that it is not that difficult to store a password securely.<br /><br />It is not as easy (if what is explained above can be called easy) to store credit card information and addresses securely, and it is likely that the majority of web site owners don't even try to do so.<br /><br />So how do you, as a web site owner, keep your users' personal information personal?<br /><br />Like this: <a href="http://en.wikipedia.org/wiki/Elliptic_curve_cryptography">Elliptic Curve Cryptography</a>. Briefly, ECC is a public/private key scheme, meaning you use one "key" (bit of data) to encrypt information and one to decrypt information. Since you don't care who encrypts your data as long as you can decrypt it, you share the "encrypt" key with everyone while keeping the "decrypt" key private, which is where the "public/private" part of the name comes from.<br /><br />The cool thing is that ECC allows you to encrypt data with very small keys. For example, normally web site traffic using the 'https://' prefix use keys which are between 1024 bytes (characters) and 4096 bytes. Compare that to this string of characters, which is the ECC public key corresponding to one of my (old) passwords:<br /><br /><pre>!Dw3K-efjB6S1A%a[Qc4jp?XOxC[XnY+6;@Zfc)ba,7^7O#6Oi(]^Q@@wSkg6h)M(]XX6?6ptt<br /></pre><br />The above string of characters is longer than a sentence, perhaps, but nowhere near the 1024 character essay. And the private key is simply as long as...say... a password. Let me state that again:<i> the actual data used to decrypt user info under the ECC scheme IS that user's password.</i> It now is possible, then, for a user to decrypt their data by typing in their password upon login to the web site. Further, since it is possible for a web site owner to not store a user's password (only its hash), <i>not even the web site owner can decrypt private user data. </i>The owner could then keep valuable meta data, such as log in and link-clicking history, while keeping data about the user which is doing the clicking private.<br /><br />Here is what to do as a website owner to store user data securely.<br /><ol><li>Store the user's salt.</li><li>Store the hash of the user's password+salt. This allows you to securely check to see whether a user entered the right password on login</li><li>Store the user's username in plain text. While unfortunate, you need to store the username in plain text so that you can look up that user's data in the database. It is then incumbent on the user to use a private username, say "superSquirrel", instead of "Daniel.Haskin". </li><li>Upon registration of a user, generate and store that user's public key based on the the password they provide. (Don't worry; it is usually intractably difficult to get a user's password based on their public key.)</li><li>Use that public key to encrypt the rest of the user's data housed within the database.</li><li>When a user logs in to the web site:</li><ol><li>The web site uses the username to look up the database entry.</li><li>The password is verified using the salt and hash.</li><li>The password is used to decrypt the user data.</li><li>The unencrypted user data can then be used while the user is logged in, but it is never recorded anywhere by the web site.</li><li>On log out (or the closing of the user session), the data is again encrypted and stored in the database.</li></ol></ol>If a hacker should hack into a web service which implements the above, the hacker cannot access anything of value (at least, anything of value to a thief). Each user entry is secured separately, so that even if the hacker had enough computing power to crack an ECC key (no mean feat), it would only yield one user entry per cracked key. There would simply not be enough time or resources to crack the entire database, even if the cracker were the federal government.<br /><br />This plan would allow any web service using it to happily comply with the NSA and give them all the information about all the web service's users. This is because personal user data would be encrypted with a key that the web service doesn't have --- the user password. The web service would still store metadata unencrypted and then link it with the encrypted user data. That way, web service could still use the metadata for targeted marketing and data mining. It also means the NSA can then analyze the metadata. This gives them enough information to fight terrorism while also guaranteeing the privacy of individuals. In our example, they they don't know who user "#1acd3fr3" is; however, if their software flags that user as a terrorist, they can get a legal warrant asking a judge if they can go after the information for that username based on other means of investigation. But even if the NSA asked a web service owner who a particular user was, the owner would not be able to tell them, because they wouldn't have access to that information. Thus, the NSA can still do their jobs, and the web service can still use customer data to make more money, but sensitive user data can still be protected from hackers and "bad apples". <br /><br /><h3>Tools of the Trade</h3><br />Any database software vendor, such as <a href="http://www.percona.com/">Percona</a> or <a href="http://www.oracle.com/index.html">Oracle</a>, can get you the underlying database software needed. As for the encryption itself, a free and open-source implementation of ECC that I've come to know and love is called <a href="http://point-at-infinity.org/seccure/">seccure</a>. Some quick scripting to complete the algorithm that I have herein outlined should get any one seriously committed to user privacy well on their way to protecting their users' private data.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/RhmWr6yeFmQ" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2014/01/how-to-comply-with-nsa-while.htmltag:blogger.com,1999:blog-4686393050407685865.post-82158571077702585922013-12-30T06:50:00.002-08:002013-12-30T12:45:31.810-08:00Dragon NaturallySpeaking, Vimperator, and EmacsMy wife got me Dragon NaturallySpeaking for Christmas. It's been fun learning how to use it, but it's been frustrating learning how to browse the Internet with it. I ended up saying a lot of hotkeys while working with Firefox, such as "press ctrl+k" and "press ctrl+pgdn".<br /><br />Then I discovered <a href="http://vocola.net/v2/">Vocola</a>, which allows you to define your own custom voice commands. That, together with <a href="https://addons.mozilla.org/en-US/firefox/addon/vimperator/">Vimperator</a>, which I have already been using, it is now a breeze to use Dragon to browse.<br /><br />I just installed Vocola according to the directions found <a href="http://vocola.net/v2/InstallVocola.asp">here.</a><br /><br />Here is my <span style="font-family: "Courier New",Courier,monospace;">.vimperatorrc</span> file:<br /><br /><pre>set hintchars='0123456789'<br />inoremap <C-a> <Ins><C-a><Ins><br />map J gT<br />map K gt<br />highlight Hint font-size:200%;color:white;background-color:red;padding:2px;<br /></pre><br />Simply put this file in your home directory. If you are using a Windows operating system, this is something like c:\Users\djhaskin987. <br /><br />Then, with Vocola installed, use Dragon NaturallySpeaking to open Firefox, and say "edit voice commands", and paste the following:<br /><br /><pre> # Voice commands for firefox<br />visit <_anything> = {Esc}":open $1";<br />close tab = {Esc}d;<br />open tab <_anything> = {Esc}":tabopen $1";<br />follow <_anything> = {Esc} f $1;<br />follow tab <_anything> = {Esc} F $1;<br />next doc = {Esc} J;<br />previous doc = {Esc} K;<br />back = {Esc} H ;<br /></pre><br />Viola! Easy browsing by speech. Just say "follow <name link="" of="">", or just "follow" and then say the number that pops up next to the link. To open a webpage, just say "visit" followed by the address. Vimperator will give you a menu of options. A couple of "press tab" and "press enter" commands later and you're in business.<br /><br />I also plan to use Vocola and Dragon NaturallySpeaking to improve my programming by defining some voice commands for Emacs, <a href="http://ergoemacs.org/emacs/using_voice_to_code.html">sort of like Tavis Rudd</a>, only Vocola is way easier to define voice commands with than Python.<br /><br />Here is my Vocola file so far for Emacs:<br /><br /></name><br /><pre># Voice commands for emacs<br /><number> := 1..99;<br />open file = {Ctrl+x}{Ctrl+f};<br />boom = {Enter};<br />undo = {Ctrl+Shift+_};<br />die = {Alt+Backspace};<br />back = {Backspace};<br />whack = \;<br />um = {Alt+b};<br />curly = "{";<br />close curly = "}";<br />paren = "(";<br />all in = ")";<br />the <_anything> = $1;<br />start = {Ctrl+a};<br />end = {Ctrl+e};<br />camelize <_anything> = {Alt+x} camelize {Enter} $1 {Enter};<br />left = {Ctrl+b};<br /><number> up = {Ctrl+u} $1 {Ctrl+p};<br /><number> down = {Ctrl+u} $1 {Ctrl+n};<br /><number> left = {Ctrl+u} $1 {Ctrl+b};<br />right = {Ctrl+f};<br />up = {Ctrl+p};<br />down = {Ctrl+n};<br />go = {Alt+f};<br />scroll down = {Ctrl+v};<br />scroll up = {Ctrl+v};<br />cut = {Ctrl+k};<br />yank = {Ctrl+y};<br />nay = {Alt+y}; </pre><br />The function "camelize" is an emacs lisp interactive function which takes a phrase like "the grand old duke of york" and turns it into "theGrandOldDukeOfYork", kind of like <a href="http://www.emacswiki.org/emacs/CamelCase">what is found in the emacs wiki</a>, but changing from space separated instead of underscore separated, and making the function interactive as well. <br /><br />I hope to also use Emacs templating like Tavis Rudd does in his video to make functions and classes by speech easier in Emacs.<br /><br />EDIT: I'm putting my vocola files for easy browsing and programming by voice in a <a href="https://github.com/djhaskin987/programmers-vocola">git repository</a>. Pull requests wecome! <img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/UpHEWrCbeYk" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2013/12/dragon-naturallyspeaking-vimperator-and.htmltag:blogger.com,1999:blog-4686393050407685865.post-30687273616187646172013-12-19T09:25:00.001-08:002013-12-19T09:33:58.265-08:00MancakesWhat do you want? I dabble.<br /><br />I have this amazing pancake recipe I made up.<br /><br />I take this from the original "German Pancake" recipe my wife found, but that was baked in the oven. This is in a pan.<br /><br />It's called a Mancake rather than a pancake for the following reasons:<br /><br /><ol><li>It has tons of eggs (protein) in it</li><li>It is dead simple -- only requires a 1/2 cup size measuring cup and a teaspoon. (For those of you who subscribe to the metric system, a 1/2 cup is 120ml and a teaspoon is 5ml).</li><li>The recipe serves one (1) hungry person (likely, therefore, a man).</li></ol>Here it is:<br /><br />1/2 cup milk<br />1/2 cup (whole wheat pastry) flour<br />2 eggs<br />4 teaspoons (olive) oil (20ml, or 1/12 cup)<br />1 teaspoon baking powder, or 1 teaspoon baking soda and 2 teaspoons (apple cider) vinegar<br />1 pinch salt<br /><br />Combine ingredients in a slightly-larger-than-normal bowl using an ordinary fork. Pre-heat your (electric) stove to a "6" (just past medium heat) while your skillet is on that stove. Pour 1/2 cup of batter onto the skillet. When there are a bunch of bubbles on the mancake, place your spatula under the right half of the large mancake and flip (or, for lefties, the left half of the mancake). Wait one minute, then take out of the pan and repeat. Makes 3 mancakes. Serves one. Enjoy.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/FuBbJ46JwmU" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2013/12/mancakes.htmltag:blogger.com,1999:blog-4686393050407685865.post-1121795475377117942013-12-16T09:56:00.000-08:002013-12-16T10:03:24.226-08:00Moving OnSo I could put another post on here about the genetic algorithm, but everything I wanted to say on the subject has been said about that particular algorithm.<br /><br />Rest assured, I have many more ideas about optimization algorithms. But let me tell you -- it's getting frustrating. A lot of my ideas about new algorithms for optimization include this <a href="http://djhaskin987.blogspot.com/2013/07/the-rankedset-optimizations-best-friend.html">RankedSet</a> idea... and it doesn't exist in standard libraries.<br /><br /><a href="http://stackoverflow.com/users/232707/michal-marczyk">Michał Marczyk</a> <a href="http://stackoverflow.com/a/18927577/850326">made one</a> for Clojure called <a href="https://github.com/michalmarczyk/avl.clj"> avl.clj</a> (great job, Michał!), and <a href="http://en.wikipedia.org/wiki/AVL_tree">AVL tree</a> implementation of what I call the RankedSet, but the genetic algorithm as below described (and other algorithms bouncing around in my head) need faster insertions/deletions and virtually no lookup. That is precisely what <a href="http://en.wikipedia.org/wiki/Red_black_trees">red-black trees</a> are better at over AVL trees. I need a red-black tree based implementation.<br /><br />So I decided to learn how to make one.<br /><br />I am currently going through <a href="http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521631246/ref=tmm_hrd_title_0">Chris Oksasaki's "Purely Functional Data Structures"</a>. (Even just reading the first chapter, you can tell <a href="http://en.wikipedia.org/wiki/Rich_Hickey">Rich Hickey</a> idolizes the guy, and for good reason.) For those who don't know, this is a seminal work on how to design your own rock-star data structures. A quote from the first chapter:<br /><blockquote class="tr_bq"><br />Rather than attempting to catalog efficient data structures for every purpose (a hopeless task!), we instead concentrate on a handful of general techniques for designing efficient functional data structures...Once you understand the techniques involved, you can easily adapt existing data structures to your particular needs, or even design new data structures from scratch. (p. 4) </blockquote>I am even learning OCaml so that I can go through it better (most of the examples in his book are in standard ML, which is to OCaml as C is to C++, as far as I can tell). <br /><br />Hopefully at some point into it I'll be able to make a RankedSet, share the implementation, and keep writing about awesome algorithms.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/Xgh7Vf1TOlg" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2013/12/moving-on.htmltag:blogger.com,1999:blog-4686393050407685865.post-48039528959313886682013-09-03T20:42:00.003-07:002013-09-04T17:16:01.316-07:00The New Genetic Aglorithm: What Makes It New In the last post of my 'New Genetic Algorithm' posts, I talked about the RankedSet, which is the backbone of the algorithm, and what makes the algorithm <i>fast</i>. In this post, I'll talk about what makes the algorithm <i>easy to use</i>.<br /><br /><h1>Keeping it Simple</h1>Nobody likes using a tool with a bunch of dials and switches on it. Would you rather use a drill with five dials on it with labels on those dials that look like they have made-up words on it? And you're thinking, "I just want to drill a hole!" <br /> <br /><br />You are not alone. Most people, when faced with using something like a drill, or washing machine, or algorithm, would much rather use an 'on' switch than anything else. <br /> <br />The thing is, most genetic algorithms that I've come across have <i>five</i> dials on it, which all need to be set properly in order for the algorithm to work: <br /><ol><li>The fitness function</li><li>When to stop</li><li>What the kill-off rate will be</li><li>What the mutation rate will be</li><li>The size of the initial population </li></ol><br /> <br />I believe that the genetic algorithm is only used, either in heavy industry, or academia, precisely because it has five dials and switches. One almost needs an algorithm to solve the problem of how to set these "dials"!<br /><br />So, a major goal of this new genetic algorithm is to take the algorithm to the masses. It asks the question: "What would a normal person care about?"<br /><br />A normal person would care about the first two things in the above list:<br /><ol><li>the fitness function and </li><li>when to stop.</li></ol><br /> <br />A "fitness function" is a set of instructions given to the algorithm to score the solutions it finds. To stick with our previous post's example, the "solutions" represent which strategy to employ in getting food for my family on the way home from work: Do I get takeout? Do I get fast food? Do I go home and cook something? etc. It's easy to tell an algorithm "I want food quickly, and I'm willing to spend a little to get good food, too." A statement like this is, in essence, the "fitness function". With this fitness function, the genetic algorithm would score 'getting takeout' high, and 'cooking at home' low. The fitness function is both easy to understand and essential for the algorithm to work, we'll probably keep this as an input to the algorithm as it is.<br /><br />The question of "when to stop" is also relatively straight forward to answer for the user of the algorithm, but hard for the algorithm itself to answer. Something like "stop when you can't find anything better" or "keep improving your solution until 7am tomorrow" is both an easy and a relative piece of information for a user to give the algorithm, while it is hard for the algorithm to guess at when to stop. See, the genetic algorithm can just keep. on. going. It will find try to find better and better solutions until you tell it to stop. This makes sense. There are a million ways, for example, to get food at the end of a work day. However, I usually know as a user when I want to stop looking for a better solutions. Telling the algorithm when to stop is telling the algorithm when the solution it's trying to find is "good enough". Therefore, this parameter also makes sense for the user to provide.<br /><br />It's the other three that can be thorns in a user's side. There is no intuition that can help the user determine what 'kill-off rate', 'mutation rate', or 'population size'. These three parameters need to be set and set well, but the only way a user would know how to set them is trial and error. The New Genetic Algorithm is cool, not only because of its back-end efficiency, but its front-end user friendliness: <i>it knows how to set those three parameters for you.</i> <br /> <h1>Setting The Parameters</h1><br /><h2>Kill-Off Rate</h2><br />Most genetic algorithms will ask you to specify a kill-off rate: a percentage of your population which should be killed off at every step of the algorithm (each "season", if you will). It asks the question: at each iteration, how many of the "weak" of the population should die? This rate also dictates the number of new solutions created at each step, since in general the algorithm should deal with a fixed population size.<br /><br />So what should our algorithm choose as its kill-off rate? 5%? 10%? 2%? All of these choices seem so arbitrary. There really isn't a choice I have found that makes more sense than the others. Too many killed off, means you won't get as good of results as you could have. Too few, and it will take a while to get there.<br /><br />It should be stated here that kill-off rate is kind of related to something which in other algorithms is called "learning rate". The higher the kill-off rate, the faster the solutions will improve; however, the slower the kill-off rate, the better the results will ultimately be, even if it takes a while to get there. The kill-off rate represents the 'price/quality' tradeoff: more quality = more time = smaller kill-off rate; less quality = faster running = greater kill-off rate. What would be <i>really</i> cool is if the algorithm could choose the kill-off rate based on how much time it was given to run (when to stop). That way the user only need specify when to stop and the algorithm knows how long to run.<br />In that light, and for reasons that will become clear later on in this series, I simply chose to kill of one (<code>1</code>) solution per step. This essentially means that the population size ultimately decides this kill-off rate. If I have <code>100</code> solutions in my population, that means the kill-off rate is <code>1%</code>. If I have only <code>10</code>, it means my kill-off rate is <code>10%</code>. This may seem like a bad thing, but what it does is that <i>it allows us to choose kill-off rate based on population size</i>. In other words, by making kill-off rate dependent on population size, we can control how fast the algorithm learns by only regulating one variable (the size of the population). This makes thinking about how to tell the algorithm how fast or slow to learn much easier. It also makes the single step of the algorithm <i>very</i> fast and gives it more predictable results.<br /> <br /><h2>Mutation Rate</h2><br />A small word should be put here about how creation of new solutions in the population works.<br /> <br />Mutation relies on the fact that, <i>all bit strings of length <code>n</code> specify a solution</i>. It flips one of its bits at random. The genetic algorithm doesn't see the solution for a solution; rather, it just sees a bunch of 1's and 0's. This is consistent with nature. Nature doesn't see a bacteria for what it is; it just sees a bunch of DNA. The 1's and 0's are the solution's "DNA". Thus by flipping one of the random bits in the solution, we <i>mutate</i> the solution.<br /><br />There is a small amount of math involved here, but not bad; just enough to keep things interesting.<br /> We want to choose a mutation rate (the percentage of the population getting this random bit flipped) intelligently. The new algorithm is herein designed to choose it to maximize the <i>diversity</i> of the population.<br /> <br />Here in our new algorithm, we want a highly diverse population. If you have many solutions that are roughly the same, what is the benefit of a population at all?<br /><br /><h4>A Side Note About How We Create New Solutions</h4><br />In the new algorithm, we will use <a href="https://en.wikipedia.org/wiki/Crossover_%28genetic_algorithm%29#One-point_crossover">single crossover</a> to create a new solution. There are lots of ways to create new solutions, but as we intimated in the beginning, we like to keep things simple in this new algorithm. This just means we pick a random number between <code>0</code> and <code>n</code> (the size of the solutions -- the number of bits they contain). Call that number <code>p</code>. The first <code>p</code> bits come from the first <code>p</code> bits of one solution (the "mom") and the rest of the bits come from the other solution (the "dad").<br /><br />Who shall we chose to make new solutions? the two best, or part of the 'party' of the elite of the population? Perhaps we could, but here in our new algorithm, let's keep things simple. We will simply take two random solutions from the population and pair them up to create a new solution. <br /><br /><h4>Why This is Important to Choosing Mutation Rate</h4><br />Now let's reiterate our problem. We need to choose mutation rate to maximize diversity of the population. In order to ascertain diversity, we need a population sample.<br /><br />But we just chose two solutions at random to create a new solution. Why don't we just use the two solutions we just chose as a small "sample" of the population of solutions? That way, we only need to retrieve two solutions per iteration, kill one off, create one, and possibly mutate one. Genious! then the iterations can be done <i>very fast</i>.<br /><br />How do we determine if the population is "diverse"? Simple: we count up how many bits at each position from <code>1</code> to <code>n</code> in the bit strings of the mom and dad solutions are the same. The more that are the same, the more "the same" the population is and the more it is due for a mutation. Then, if we do decide to mutate a solution, we will simply mutate one of the solutions and re-insert it back into our population.<br /><br />We will use this formula to determine the probability of whether we should mutate one of the parents:<br /><br /><pre>P(m) = 4*(1/2*k/n - 1/2)^2</pre><pre> </pre>Where <code>P(m)</code> is the probability that we should mutate one of the solutions, <code>n</code> is the number of bit positions for solutions, and <code>k</code> is the number of bit positions where both parents share the same value.<br /><br />This is a nice, easy-to-compute, bowl-shaped function that actually looks a lot like the <a href="https://en.wikipedia.org/wiki/Entropy_%28information_theory%29">information entropy function</a> for two values. That's math-speak for "it worky."<br /><br />Think about it -- If about half the bits are the same, which you would expect that from two random solutions, the probability of mutation is small, since the two solutions are expected to look pretty different from each other -- around half their positions are different. The closer <code>k/n</code> gets to <code>1</code> or <code>0</code>, though, that value goes to <code>1</code>, or <code>100%</code>, meaning that one of them really should be mutated, since each solution looks too much like the other, or that they look like polar opposites, both types of which we would not expect in a more diverse population.<br /><br />After we have computed <code>P(m)</code>, then we just get a random number between <code>0</code> and 1. Call it <code>r</code>. If <code>r < P(m)</code>, then we mutate one of the new solutions and re-introduce it to the population. If it isn't, we simply put both parents back un-mutated.<br /><br />There! we have chosen a good method for choosing mutation rate dynamically. It is chosen at each iteration, is easy to compute, and makes sense for the goal.<br /><br /><h3>Population Size</h3><br />As New Genetic Algorithm designers, it's our job to figure out how best to determine population size. This is the size of the RankedSet discussed in the last post of the number of "indigenous" solutions that we'll keep around. We need a base population if we want to kill some off and create more and still have the genetic algorithm to work. So how do we choose population size?<br /><br />Remember earlier, when I said that by determining population size and keeping the kill-off rate at one solution, we determine the 'learning rate'? When we have a small population size, say 10, the learning rate/kill off rate is <code>1 / 10 = 10%</code>. This means the algorithm will improve fast, but also plateu fast.<br /><br />Why don't we just wait for it to plateu at some improvement level, then when it does, we increase the size of the population? By doing so, we decrease the learning rate, allowing the algorithm to find an even better solution, even if more slowly.<br /><br />To keep things simple, let's just say this: We'll start off at a population size of <code>16</code>. When we find that no more "improvement" is to be found within the population, we double population size and continue iterating. We keep doing this until we are supposed to stop, which is something that the user supplies!<br /><br />Simple, easy, intuitive, and easy to implement. These are the goals of the new genetic algorithm.<br /> <img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/55FswYQZ2ac" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2013/09/the-new-genetic-aglorithm-what-makes-it.htmltag:blogger.com,1999:blog-4686393050407685865.post-66900305369652177992013-07-05T19:16:00.003-07:002013-07-19T18:53:29.258-07:00The RankedSet: Optimization's Best Friend<br />This post is the second post about the 'New Genetic Algorithm' that I posted about previously.<br /><br /><h1>What We Need</h1>See, when you're running the genetic algorithm -- that nifty way to solve problems by computer -- you need to store different solutions to the same problem. For example, suppose I need dinner for my family tonight. Do I cook at home, grab some fast food, or buy a TV dinner at the local grocery market? These are different solutions to the same problem: my family needs food.<br /><br />While the genetic algorithm (any genetic algorithm, including this new one) is running, it needs to maintain a "population" of such solutions. It keeps around, say, 100 solutions, kills off some, and adds new ones, but it always stores so many solutions (e.g. 100) at all times. In my new genetic algorithm, it will be important for reasons explained in a later post for the algorithm to be able to figure out the <i>rank</i> of each solution. Rather than knowing how much better one solution is from another, I feel it is important only to tell which solution is better than the other. When we make a buying decision, it does not matter if one option is a little bit better or way better, we usually just take the better option. This idea is important, and in the algorithm it will become important to be able to find a solution within the "population" and be able also to delete it <i>based on its rank</i>. I need to be able to say to the data structure, "give me the 45th best solution" and out it pops. I also need to be able to say, "kill off the 32nd solution". So, in order to store the population so that I can easily find, delete (kill off), insert (introduce) a solution into my population, the question is: what is the best way to store my population in a computer?<br /><br />It turns out, there really isn't a data structure in any standard library I've found that can do the job. By the way, for those purist logicians who are craving a formal specification of what 'the job' is, sink your teeth into this:<br /><br /><ul><li>The data structure needs to store information about each solution. If this is the 'bring home the bacon' example, it needs to store stuff like 'store location', 'what to buy', etc.</li><li>The data structure needs to store information about the <i>rank</i> (e.g., best, second-best, 43rd-best) of each solution.</li><li>The data structure needs to have efficient retrieval, deletion, and insertion. It needs to be able to delete a solution given its rank, and retrieve a solution given its rank.</li></ul><br /><h1>Fanfare, Please: Enter the RankedSet</h1><h3>Why We Like It</h3><div>The RankedSet will solve the problems I have stated above. You can store a solution to a problem in it, you can tell the set how great the solution is, and it will assign ranks for you based on how good each solution is. It provides retrieval and deletion based on rank and all retrieval, deletion, and insertion runs in logarhmic time. For those non-nerds out there, that means it does what we want it to, and it does it at speeds that take the cake.</div><div><br /></div><div>Here's how it works: when we insert a solution into the set, we give it two values: how good the solution is, which we will call the <i>index</i>, and then the information about the solution itself, which we will call the <i>payload</i>. Since we'll rank the solutions in the set based on the first value, it needs to be a number -- a score, or perhaps in some cases, a monetary amount, etc. The payload can be anything we want, but in this case it is information about the different solution that we will put here.</div><div><br /></div><h3>How It Works</h3><div>But how does it <i>work</i>, you say. That's the juicy part, right?</div><div><br /></div><div>Computer Scientists know that what I am about to describe, is, basically, a <i><a href="http://en.wikipedia.org/wiki/Binary_search_tree">Binary Search Tree</a></i>, or BST. Each solution has at most two "children" solutions--one with a greater index than itself, and one with a smaller index.</div><div></div><div>With each solution is stored three things:</div><div><ol><li>The solution information itself.</li><li>How "good" the solution is.</li><li>How many other solutions are "downstream", or, how many "descendants" the solution has (including itself).</li></ol>It's number 3 in the above list that's the interesting bit. every other part of the description of how the solutions are stored is just a regular ol' BST, easily found in most any standard library in most any computer language. But no BST I've ever found has #3 in the above list stored in it, and so cannot function as a RankedSet.</div><div><br /></div><div>Note that the value for #3 can never be empty. If there is a solution stored with no "children" solutions, #3 value is just "1", since it is the number of solutions that are descended from a node, <i>including itself</i>.</div><div><br /></div><div>If every solution in the tree stores #3, then it becomes easy for the BST to look up a solution based on rank. Say that I need the 13th best solution in the BST. I ask the "root" node (the very first solution, with no parents and all children) to give me the 13th best. It asks the 'greater' of its children how many children it has. Say that number is 10. To few. It asks its lesser child again how many children that it has, which might be 20. So, it tells its lesser child to find the 2nd best solution in its family (13 minus the 10 best on the greater side, take away the root node itself, which leaves 2). If that sound hokey to you, then just trust me: it works, and it's fast.</div><div><br /></div><div>Further explanation would boggle the mind of those of my non-egg-head readers, and is not necessary for those already familiar with binary search trees. Suffice it to say that caching the number of descendants of a solution, including the solution itself, allows us to find and delete solutions based on rank.<br /></div><br /><h1>So What's It All Mean?</h1><br /><div>It means that we can now construct an algorithm that does not have to concern itself with how great a solution is, only if it is the best one. At the same time, it also means that the algorithm only has to know how good a solution is when it is inserted into the population, and from then on it need only talk about weeding out solutions that are weak, like the 75th best solution, and promoting the strong ones, like the 2nd solution. It means that it can talk about the rank of those solutions without ever actually retrieving them until it is time to kill the weak and create the strong. This makes our algorithm really <i>fast</i> and very <i>effective.</i></div><div><i><br /></i></div><h1>Up Next</h1>In the next post I will talk about how the algorithm uses the RankedSet, how it chooses how many weak to kill off and spawn, how it chooses how many solutions to mutate, and how easy those choices make it for programmers to use the new genetic algorithm to solve the next big problems.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/TXX1R-dFY1g" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2013/07/the-rankedset-optimizations-best-friend.htmltag:blogger.com,1999:blog-4686393050407685865.post-16253430376767964512013-05-20T09:23:00.002-07:002013-07-05T16:54:35.587-07:00A New Genetic AlgorithmI have recently been fascinated with the genetic algorithm, which is a method that allows you to solve pretty much any big problem via computer, like finding the most nutritional, affordable lunches for a week for your kids, or what's the best NFL schedule (funny that these problems are provably equivalent).<br /><br />The idea is simple. generate a bunch of mediocre solutions, kill off (eliminate) the weak ones, use the stronger ones to sire more solutions, mutate a gene (aspect) of some solution or other just to shake things up, and repeat.<br /><br />The problem is all of the different ways to do it. Should we mutate 5% of the solutions, or 10%? How many solutions should we kill off at a time? How many should we make? There are alot of design decisions to make when using this algorithm.<br /><br />And then there's efficiency to think about. How should the solutions be represented (e.g., what stats should be encoded)? What data structures should be used? What complexity class is acceptable (has to do with how much time the program takes to run)? These questions may sound unimportant from a business perspective, but it's the difference in an app between 'wow, that was zippy' and 'that sure took a long time to load'.<br /><br />The 'data structure/data representation' question is particularly important because not only does it deal with how fast the program runs, but how maintable the code base will be in the future. When, as a programmer, I code up a solution to a problem, it is very difficult to change the way the data is represented and stored in the future.<br /><br />I have given all these problems some thought, and I have come up with (I believe) a very good solution. The data representation is versatile. The data structure is maintainable, efficient, and convenient. Best of all, I have found a convenient way to get rid of all those parameters (i.e., I have adequately answered all of the 'how/what' questions about the algorithm, listed above).<br /><br />I will post a series of articles detailing what I did to create a genetic algorithm which needs only be given a fitness function and the size of the population of solutions -- nothing else. It is fast, usable in a highly varied number of fields, and its operation is intuitive.<br /><br />My first post will deal with the data structure / data representation problem. My second will deal with removing the how-many-to-kill-off/how-many-to-reproduce/how-many-to-mutate problem. My third post will tie it all together. Let me know in the comments below to join the conversation and let me know how I'm doing as I go. I will try to answer any questions given.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/0EWlJ2wESEM" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2013/05/a-new-genetic-algorithm.htmltag:blogger.com,1999:blog-4686393050407685865.post-47757178625042392622012-04-18T17:43:00.000-07:002012-04-18T17:43:19.432-07:002/3 Swing Follow-upSo the algorithm I spoke of in my last post is actually very similar to an algorithm known as v-opt. The difference between 2/3 swing and v-opt is that in v-opt, before ensuring that the solution is an n-opt minima, first ensures that it is also a k-minima for all k < n. So then, the solution is guaranteed to be gets to a 2-opt minima, then a 3-opt minima, and stops, whereas mine swings back and forth. This difference is further seen when 4-opt is introduced. Then, v-opt would find a 2-opt minima, then a three-opt minima, then ensure it is at a two-opt minima again, then ensure it is in a three-opt minima again, etc. Finally, when both 2-opt and 3-opt minima is found, it ensures it is in a four-opt minima, then a two-opt minima, then a three-opt minima, then a two-opt minima again, until it is in both 2- and 3-opt minimas before it checks for 4-opt minima, etc. I know, kinda confusing.<br />Mine just ensures it's in a 2-opt minima, and goes round-robin instead of making sure the solution is a minima of all opt's below the current one (both 2- and 3- opt before we ensure 4-optimality). It just goes round and round - 2-opt, then 3-, then 4-, then 2-, then 3-, then 4-,... I found this approach did alot better than conventional v-opt as I understand it.<br />That may have been a little confusing, but I wanted to make sure I tied in my own research with what's already out there.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/lFj90oZmwPU" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2012/04/23-swing-follow-up.htmltag:blogger.com,1999:blog-4686393050407685865.post-79094131230227088902012-02-28T07:43:00.003-08:002012-02-28T07:51:13.665-08:00The TSP Refinement Solution, Continued: 2/3 Swing<span style="font-family: inherit;">The work on the algorithm I spoke of in my last post bore fruit! It works very well and uses perhaps previously-unbeknownst-insight. The outline of the finished product I lay before you now.</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">The attached contains the empirical data I gathered about how well my algorithm works. </span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">I received some surprises, and other things did not surprise me. I guessed my algorithm would perform somewhere around O[(n^3)log(n)], and as you can see by the graph, it is quite possible that it did. I was surprised to find, however, that the relationship between how well the greedy algorithm did versus how well my solver did (I call it the "2/3 swing" algorithm) was linear - about 1.3x better than greedy. Perhaps this is because I started out with greedy and can only get so far refining any given solution. Perhaps if I started out with a closer approximation, I might get closer to optimality.</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">You see, the way my algorithm works is that it takes an initial arbitrary solution - in the case of the data provided, the algorithm started out with a random greedy solution - and, essentially, then gets into a 2-opt local minima. But the insight I gained in creating this algorithm is that a 2-opt local minima is not necessarily a 3-opt local minima. In fact, it rarely is. This is like multi-dimensional gradient descent - as there is rarely a minima across all dimensions in gradient descent, so there is rarely a minima across all opt's. At least, that is the idea of the algorithm. </span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">Here's another clincher: getting into a 2-opt minima for assymetric, incomplete graphs (TSP city maps) has roughly the same complexity as getting into a 3-opt minima, since a linearly-large portion of the path must be reversed for each check to see if the change is an improvement. This makes a thorough 2-opt check, whose search space is in O(n^2), take O(n^3) time. To find a 3-opt local minima, the search space is in O(n^3) and the check is in O(1), so finding a local 2-opt minima, then trying to find a local 3-opt minima, doesn't cost much more by way of complexity, residing only in a constant factor increase in time.</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">The way that this algorithm gets itself into O(n^3*log(n)) time (or O(n^3.22), if the graph's regression line is to be believed) is by continually "swinging" back and forth between using 2-opt and 3-opt to find the next minima, so that a series of operations in O(n^3) time is looped over a few times. Between using 2-opt and 3-opt, city swapping is employed (taking two arbitrary cities on the best route so far and switching their places as far as order of visitation if such a switch improves the route's score) so as to "mix the bag" between swings. This operation is a small subset of 4-opt, and because it is only in O(n^2) it does not hurt complexity much. Additionaly, since this algorithm works on asymmetric city maps, a reversal of the direction of the route is checked to see if it improves the score on each "swing". This check is linear in time and also does not greatly affect the complexity of the algorithm. Thus the algorithm follows:</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">best route so far = (initial-approximation-solution)</span><br /><span style="font-family: inherit;">best cost = infinity </span><br /><span style="font-family: inherit;">while best cost > best route so far's cost</span><br /><span style="font-family: inherit;"> best cost = best route so far's cost</span><br /><span style="font-family: inherit;"> reverse best route so far if that improves it's score</span><br /><span style="font-family: inherit;"> best route so far = (next 2-opt local minima)</span><br /><span style="font-family: inherit;"> best route so far = (next swap-cities local minima)</span><br /><span style="font-family: inherit;"> best route so far = (next 3-opt local minima)</span><br /><span style="font-family: inherit;"> best route so far = (next swap-cities local minima)</span><br /><span style="font-family: inherit;">return best route so far</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">As I cannot post the original data, I will only post the graphs. Original data upon request.</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">Technical Data:</span><br /><span style="font-family: inherit;">Platform used: C# on .NET 4, running on an Acer Aspire One 532 netbook</span><br /><span style="font-family: inherit;">Initial solution (used in refinement): random greedy</span><br /><span style="font-family: inherit;">City Map: Assymetric, Incomplete</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">Acknowledgements:</span><br /><span style="font-family: inherit;">I used the C# TSP Framework provided by the CS department of Brigham Young University.</span><br /><span style="font-family: inherit;">Code was used in studying this problem which was written by Jimmy Hales (see previous post), although all the code used in the 2/3 swing algorithm is original to the author of this post. Dr. Tony Martinez of Brigham Young University served as adviser during my study of this algorithm, and thanks to him I continued to work on it.</span><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-iHUY0YPBNFc/T0z0yoDYfWI/AAAAAAAAAa8/f9VoJQDWIwY/s1600/my+scores+vs+greedy.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="207" src="http://1.bp.blogspot.com/-iHUY0YPBNFc/T0z0yoDYfWI/AAAAAAAAAa8/f9VoJQDWIwY/s400/my+scores+vs+greedy.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/-ZG_bbfZfqqw/T0z09MNPbiI/AAAAAAAAAbE/jIBJfRyK7D8/s1600/my+times.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="250" src="http://4.bp.blogspot.com/-ZG_bbfZfqqw/T0z09MNPbiI/AAAAAAAAAbE/jIBJfRyK7D8/s400/my+times.png" width="400" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div><br /></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;"><br /></span></div><img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/eYEgyQ_x2JU" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2012/02/tsp-refinement-solution-continued-23.htmltag:blogger.com,1999:blog-4686393050407685865.post-71011600603438798352012-01-04T19:37:00.000-08:002012-01-04T19:52:09.108-08:00An Idea for the Refinement of a TSP Solution<span style="font-family: inherit;">Although I found through experiment that my probabilistic approach to finding a good TSP solution didn't work so well, I did manage to find a polynomial time algorithm that can take an arbitrary solution to the Traveling Salesperson Problem (TSP) and refine it to the optimal solution (with what I have tested so far). I do not know if this polynomial refinement-to-optimality is possible for solutions bigger than 20, as the exponential branch-and-bound solver at my disposal can't do very much given the hardware I have on which to run it.</span><br /><b><span style="background-color: white; font-family: inherit;"><br /></span></b><br /><span style="font-family: inherit;"><b>Now, I think what I have found here MIGHT be awesome. </b></span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">At any rate, I can explain what it does.</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">First, we assume an asymmetric directed graph of cites, wherein not every possible edge exists -- i.e. The number of edges in the graph |E| < |V|^2, where |V| is the number of vertices (cities) in the graph (map of cities). For simplicity, if an edge does not exist from one city to another, the reverse edge also does not exist. It can be quickly checked that this problem is still NP-Complete.</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">We may take this graph to be a map of roads between cities, and the weights on the edges (roads) to be a score of them based on the distance between the cities and the elevation difference between the cities, i.e. if one city is higher in elevation than another, the edge going from the higher to the lower is going to be scored lower than the edge which goes from the lower to the higher, because it is easier to go downhill. Looking at such a real map of cities and creating a graph from it, by scoring the edges as above, we find a distinct pattern in the optimal solution to the traveling salesman tour of the cities considered:</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">In some sense, the solution forms a "polygon" in the sense that no loops are created. So, this:</span><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-jxpF6dSFptA/TwUT4CoWvgI/AAAAAAAAAaQ/wlSZusqF92E/s1600/optimal-tour.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="background-color: white; color: black; font-family: inherit;"><img border="0" height="320" src="http://2.bp.blogspot.com/-jxpF6dSFptA/TwUT4CoWvgI/AAAAAAAAAaQ/wlSZusqF92E/s320/optimal-tour.png" width="303" /></span></a></div><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">would be a better solution than this:</span><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-lnqgghmt4vg/TwUT-DfZxUI/AAAAAAAAAac/Yt6nwHrRz1k/s1600/twisted.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: inherit;"><img border="0" height="320" src="http://2.bp.blogspot.com/-lnqgghmt4vg/TwUT-DfZxUI/AAAAAAAAAac/Yt6nwHrRz1k/s320/twisted.png" width="303" /></span></a></div><span style="font-family: inherit;">Provided we are looking at the "actual" city map, this is a fairly good heuristic for "goodness" of a solution, if not a requirement for optimality. Looking at the actual city map is important because the actual euclidean distance between cities is taken into account in the scoring of edges, and so these "twists" show up on the actual map, whereas if we just have the graph information, this intuition would not make sense since placement of the node on paper of the equivalent graph has nothing to do with the edge weight. Again, it should be noted that the graph (city map) upon which we consider is asymetric and incomplete, and so is still worthy of discussion.</span><br /><span style="font-family: inherit;"><br /></span><br /><span style="font-family: inherit;">To further shed light on this discussion, it will be assumed that the optimal tour through a given number of cities will be represented by a list of cities, with the order that the city appears in the list being the order of its visitation on the TSP tour. I now take from an excerpt of an email I sent to my CS professor Dr. Tony Martinez on the subject.</span><br /><blockquote class="tr_bq"><span style="font-family: inherit;"><br />To refine a given approximate solution, I observed (as explained above) that approximate solutions often have "twists" in them - that is, they were not polygons since their vertices crossed. So I take the solution and try untwisting any arbitrary segment of the solution (that is, reversing that segment - e.g. take the segment # 2, 3, 4, 1, 5 and change it to # 5, 1, 4, 3, 2) and see if that operation improves the score. If it does, I return the improved route, else I return the route the untwisting method was given. <i>[author's comment: if done properly, this part of the algorithm can be done in O(n^2) time.] </i><br />Now (empirically) I have observed that the approximate solution is now a polygon (no twists). But it may not be the "right" polygon. To try a different polygon, I simply take an arbitrary subsegment of the solution and splice it into a different part of the whole solution. Example: If we have a solution of Cities # 2, 4, 7, 5, 8, 1, we take an arbitrary sub segment of cities # 4, 7, 5 and try the solution where they are inserted in between 8 and 1 to produce # 2, 8, 4, 7, 5, 1. I try all such possible splice combinations, and see if they improve the score, returning any improvements. This search space, though it be search by brute force, is only O(n^3) large (what's more, being a brute force search, this and other improvement spaces given below can be searched in parallel). I find (again, empirically with our CS312 TSP <i>[Framework]</i> code) that this operation changes the "polygon" to a more optimal one.Finally, for sugar, I take this new and improved solution and select two arbitrary cities along its path and swap them, so that a tour which was city # 2, 3, 8, 7, 1, 4 becomes # 2, 1, 8, 7, 3, 4 if we swap the cities 1 and 3, thus changing the order in which they are visited.<br />I repeat these three steps - untwisting, segment swapping, and city swapping - for as long as they "help", or as long as any one of them return an improved solution. I find that the number of repetitions is usually small - 3 or 4 times for 50 cities (when it is given a best-of-greedy initial approximate solution, which is an algorithm in O(n^2) time). <i>[author's comment: these were my results when, instead of stopping during untwisting/segment splicing/city swapping at the first improvement found, I tried all available twists/splices/swaps at one time and used the best of those. The results might be higher if the suggested stop-at-first-improvement approach is taken.]</i><br />For 20 Cities, I have verified that it spits out the optimal solution over and over again, and in much faster time than branch and bound. I do not have the resources to try for the optimal solution for more than 20 cities using C# code on my laptop <i>[which is a netbook. Details: Acer AspireOne 532h, 2GB RAM, 1.66 GHz processor, running C# .NET executable under Windows 7 Starter]</i>.</span></blockquote><span style="background-color: white; font-family: inherit;"><br /></span><br /><div><span style="font-family: inherit;"><b>Thus, I believe this whole algorithm runs in O(N^4) time, which is certainly not exponential</b>. The inner loop (untwisting, splicing, swapping) can be done in O(N^3) time and O(N) space, and it is entirely possible that in fact this algorithm is in O(n^3*log N) time, more empirical study needs to be done to decide if that is indeed the case. While largely untested for bigger N, in the tests I have run it finds the optimal solution every time for city maps with city counts < 20. I know, it's not a big number, but this may still be a very good refinement of a given solution, if not a way to find the optimal solution. </span></div><div><span style="font-family: inherit;"><br /></span></div><div><span style="font-family: inherit;"><b>I wonder if anyone could try this method of solution refinement and corroborate my results</b>. Thank you all so much for your comments. I hope someone can further this effort by trying this refinement solution out themselves and comparing their results to known optimal solutions of the graphs upon which they are testing this refinement solution.</span></div><div><span style="font-family: inherit;"><br /></span></div><div><i><u><span style="font-family: inherit;">Acknowledgments: The code for the Branch-and-Bound solver I used is authored by Jimmy Hales. The C# framework out of which I performed the empirical tests was given to me by the CS Department of Brigham Young University as part of a class assignment for CS312, mentioned in the above letter excerpt as the CS312 TSP (Framework) code.</span></u></i></div><img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/hSE2usAcvOA" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2012/01/idea-for-refinement-of-tsp-solution.htmltag:blogger.com,1999:blog-4686393050407685865.post-44905515038045019842012-01-04T17:57:00.000-08:002012-01-04T17:57:44.628-08:00Update on the Probabilistic TSP AlgorithmBasically?<br /><br />It failed. Miserably. If we rated the edges based on what I said below, it may have even given us the worst possible path (a great achievement if it were so!) and if we took the edge weights into account in the ratings, the algorithm pretty much spat out roughly what a greedy solution would have anyway. However, I am glad to have done it. It gave me a lot to think about with the Traveling Salesperson problem.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/iOOgChAoH1I" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2012/01/update-on-probabilistic-tsp-algorithm.htmltag:blogger.com,1999:blog-4686393050407685865.post-8851123742123683382011-11-22T06:05:00.000-08:002011-11-22T06:05:16.519-08:00An Idea for a Probabilistic Approximation of the Solution to the Travelling Salesman ProblemIn one of my classes here at Brigham Young, our group has been asked to come up with a unique idea for getting a good approximation to an optimal tour in the traveling salesman problem. Here's the idea I came up with. <br /><br />I wanted to bring statistics to the table, knowing about such algorithms as Monte Carlo Integration and others which took an unsolvable or hard problem and managed its size simply by taking samples of the bigger problem. The question was: How do you take a "sample" of an optimal traveling salesman tour?<br /><br />The idea came to select three cities at random, and then use Djikstra's Algorithm (or the Bellman-Ford Algorithm, in the case of negative edges) to find the shortest path from the first to the second, the second to the third, and the third back to the first again, making sure these paths do not cross. If there is no such path, we start over and pick three other random cities until we find a cycle in the way just described which connects them. Such a cycle we would call a <i>subcycle</i>, and it would represent a sub-optimal approximation to the optimal tour (it takes the shortest route across a subset of the cities in the graph).<br /><br />Then, we rate the edges that were used in this subcycle. Initially, all the ratings associated with all the edges are 0. Each time we find a subcycle, we add <i>k/N</i> to each edge that is used in that subcycle, where <i>k</i> is the number of cities in the subcycle, and <i>N</i> is the total number of cities in the graph.<br /><br />We then repeat this rating process hundreds or thousands of times, accumulating ratings for the edges that fall in these random subcycles as described above. In our group project, we have 30 seconds to find a solution for an arbitrarily-sized graph, so we just decided to run the rating process described above for 28 seconds, so that many samples could be taken.<br /><br />All that is left to do now is to take this information and create a solution. This is easily done by finding the first tour through all the cities, trying first the edges with the highest rating. The hope is that this final solution will be a good approximation to the optimal solution.<br /><br />We have not yet coded this up, but we are in the process of doing so. I'll post here to let the world know how well it worked out. I'm very excited to see how well this works!<br /><br />I welcome any comments any of you may have on how well this may or may not work. Please feel free to respond to this post!<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/sOe8zrR9ABI" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2011/11/idea-for-probabilistic-approximation-of.htmltag:blogger.com,1999:blog-4686393050407685865.post-8576924922687409012011-11-15T06:20:00.000-08:002011-11-15T06:22:01.529-08:00.vimrc Goodies: Literal LambdaI recently took to programming in racket after starting to take a class from Jay McCarthy (twitter: @jeapostrophe). Racket is a scheme-based language constructed specifically with industrial use in mind, which means it is based on some pretty solid theory while also posessing, like perl and php, a package management system (<a href="http://planet.racket-lang.org/">PLaneT</a>), a JIT compiler, and other goodies that make it a great language to use in the real world.<br /><br />This language, along with perl (given that 'use lambda' is invoked), allows the programmer to insert an acutal unicode lambda instead of the keyword 'lambda'. DrRacket, racket's native IDE, allows you to insert this character by pressing 'CTRL+\' . After looking at <a href="http://vim.wikia.com/wiki/Working_with_Unicode">this page</a> and others, I found I could do this in vim, too.<br /><br />I put the following lines in my .vimrc file (this same entry worked in my _vimrc file, for the windows version, as well):<br /><br /><span style="font-family: "Courier New",Courier,monospace;">if has("multi_byte")</span><br /><span style="font-family: "Courier New",Courier,monospace;"> if &termencoding == ""</span><br /><span style="font-family: "Courier New",Courier,monospace;"> let &termencoding = &encoding</span><br /><span style="font-family: "Courier New",Courier,monospace;"> endif</span><br /><span style="font-family: "Courier New",Courier,monospace;"> set encoding=utf-8</span><br /><span style="font-family: "Courier New",Courier,monospace;"> setglobal fileencoding=utf-8</span><br /><span style="font-family: "Courier New",Courier,monospace;"> "setglobal bomb</span><br /><span style="font-family: "Courier New",Courier,monospace;"> set fileencodings=ucs-bom,utf-8,latin1</span><br /><span style="font-family: "Courier New",Courier,monospace;">endif</span><br /><br /><span style="font-family: "Courier New",Courier,monospace;">map! ^\ ^Qu03bb</span><br /><br /><br />I inserted the special characters '^\' (CTRL-\) and ^Q (CTRL-Q) by using the normal vim way: in insert mode, type CTRL-V, then whatever control character you need to. For example, I inserted '^\' by typing CTRL-V, CTRL-\. For CTRL-Q, it was trickier. CTRL-Q is usually a specially bound command, so in order to insert it I had to use its octal number ordinal: CTRL-V, 017, were the keys I typed to insert that character.<br /><br />Now whenever I'm editing a file, I type CTRL-\ and out pops a bonefied lambda!<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/Fi958DaNE9g" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2011/11/vimrc-goodies-literal-lambda.htmltag:blogger.com,1999:blog-4686393050407685865.post-41543881259962835472011-07-29T11:23:00.000-07:002011-07-29T11:37:00.350-07:00Tag Cloud of Programming Languages Based on PopularityThe following tag cloud was made by creating a text file with a given programing language's name repeated over and over, with one occurrence of the language's name appearing in the text file for each 100,000 results Google yielded for the phrase '"<language's name="">" programming language'. It has some interesting results. Please feel free to comment on its accuracy/inaccuracy, as I am very interested to know exactly how accurate the Google searches are. Enjoy!</language's><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-oGdBt9Q4hvs/TjL6dGL9FRI/AAAAAAAAAY0/gVIuFx5tUqQ/s1600/programming_languages.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="130" src="http://2.bp.blogspot.com/-oGdBt9Q4hvs/TjL6dGL9FRI/AAAAAAAAAY0/gVIuFx5tUqQ/s400/programming_languages.png" width="400" /></a></div><img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/w1u_jDnvi90" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2011/07/tag-cloud-of-programming-languages.htmltag:blogger.com,1999:blog-4686393050407685865.post-48599097559124557542011-04-03T10:58:00.000-07:002011-04-03T10:58:10.404-07:00Best Combo for Facebook, Twitter, and ChatAs cool as TweetDeck is, have you ever looked at its privacy policy? yeck. many other similiar applications have similiar disclaimers in their privacy policies or ads all over the place. For windows users, there is a solution.<br /><br />For chat: Pidgin. Being open source, their's no ads and you're not selling your soul to use it. It works well, and with virtually any protocol (facebook, google, AIM, ...)<br /><br />For Twitter/Facebook/Digg/RSS/Etc. feeds: MahTweets. It is open source, using Microsoft's new Open Source license. Its interface is clean, it is customizable, and it is a CLIENT. it is not something you need to open your browser to use.<br /><br />I've been looking for a pair of applications like this for a while. I hope others find this useful.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/Kin7xHNwGDY" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2011/04/best-combo-for-facebook-twitter-and.htmltag:blogger.com,1999:blog-4686393050407685865.post-76960442426382940372011-04-03T10:24:00.000-07:002011-04-03T10:27:51.645-07:00Fuzzy Logic III: Proof Construction<div style="font-family: Georgia,"Times New Roman",serif;">For those burning with questions on how to actually write a fuzzy logic proof. Even though the law of contradiction doesn't generally hold falor fuzzy logic, the normal rules of fuzzy logic do, with some extended functionality to deal with uncertainty.</div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">I will write about some of the basic rules of natural deduction here. from there, It should be readily seen how the rest of the rules follow.</div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">Before I move forward, it should be noted that last time, we worked with two different systems of logic: minimization (a & b = min(a,b)) and additive (a & b = max(0, x + y - 1) ) with negation being the operation (1-a) and with DeMorgan's Law adopted as an axiom.</div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">Since the things I am about to write about apply to <i>all</i> fuzzy logics, I shall refer to the function which evaluates the certainty of a disjunction based on the certainties of the disjuncts as <b>d(x,y)</b>. Therefore, for minimization logic, d(x,y) = max(x,y) (see previous post for more details). The same goes for the function which evaluates the certainty of a conjunct of, say, x and y based on the certainties of x and y themselves. Such a function (which evaluates the certainty of a conjunct) is here written as <b>c(x,y)</b>.</div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;">Writing Convention </span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><span style="font-size: small;">In this document, I will format my proofs as follows:</span></span></div><table style="font-family: Georgia,"Times New Roman",serif;"><tbody><tr><td>#</td><td> assertion</td><td> certainty</td><td> justification</td></tr></tbody></table><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">So therefore, with fuzzy logic proofs we deal with <i>three</i> columns.</div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">As an example:</div><br /><div style="font-family: "Courier New",Courier,monospace;">1. P 50% Premise</div><div style="font-family: "Courier New",Courier,monospace;">2. Q 80% Premise</div><div style="font-family: "Courier New",Courier,monospace;">3. R 30% Premise</div><div style="font-family: "Courier New",Courier,monospace;"><br /></div><div style="font-family: inherit;"><br /><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;">Conjunction (Combination)</span></div></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><br /></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><span style="font-size: small;">In Fuzzy Logic, Conjunction (P , Q |= P & Q) works quite the same as conventional logic, with the extension that the attached conjunct is simply the same as c(x,y) for the logic with which we are dealing.</span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><span style="font-size: small;"><br /></span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><span style="font-size: small;">Example (taken from the example under "Writing Convention":)</span></span></div><div style="font-family: inherit;"><span style="font-size: large;"><span style="font-size: small;"><br /></span></span></div><div style="font-family: inherit;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">1. P 50% Premise</span></span></span></div><div style="font-family: inherit;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">2. Q 70% Premise</span></span></span></div><div style="font-family: inherit;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> </span><span style="font-family: "Courier New",Courier,monospace;">3. P&Q 50% 1,2, Conjunction (using minimization logic)</span></span></span></div><div style="font-family: inherit;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">===</span></span></span></div><div style="font-family: inherit;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">3. p&Q 20% 1,2, Conjunction (using additive logic)</span></span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><span style="font-size: small;"><br /></span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-size: large;">Disjunction (Addition)</span></span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><div class="separator" style="clear: both; text-align: center;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-size: large;"><span style="font-size: small;">The same goes for dysjunction as for conjunction, namely, given p and q, p | q can be attached with the certainty given by d(p,q). P|Q above would therefore take on the values 70% and 100%, respectively.</span></span></span></span> </div></div><div style="font-family: inherit;"><div class="separator" style="clear: both; font-family: Georgia,"Times New Roman",serif; text-align: center;"><a href="http://1.bp.blogspot.com/-cklXzRhGlQk/TZilPPWBtuI/AAAAAAAAAX0/lRVZD8A3dA4/s1600/1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-size: large;"><span style="font-size: small;">When adding any old proposition, say <i>p</i>, one which we are not given the certainty value of, we write </span></span></span></span><a href="http://1.bp.blogspot.com/-cklXzRhGlQk/TZilPPWBtuI/AAAAAAAAAX0/lRVZD8A3dA4/s1600/1.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-cklXzRhGlQk/TZilPPWBtuI/AAAAAAAAAX0/lRVZD8A3dA4/s1600/1.gif" /></a>, if the proposition to which one attaches <i>p</i> has a certainty of 30%, for example.</div><br /><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;">Modus Ponens</span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div class="separator" style="clear: both; font-family: Georgia,"Times New Roman",serif; text-align: center;"><a href="http://2.bp.blogspot.com/-NGLe_6Ny-Tg/TZimZCQhpsI/AAAAAAAAAX4/-j6_beb3vms/s1600/2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div><div class="separator" style="clear: both; font-family: Georgia,"Times New Roman",serif; text-align: center;"><a href="http://3.bp.blogspot.com/-ZjYVRcm0t3k/TZimmFCtaAI/AAAAAAAAAX8/xMo9Gs6H_w0/s1600/2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><br /></a></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: small;">As I said in my last post, we are not guarunteed the law of contradiction. In conventional logi c, it is sufficient to use Contradiction along with Conditional Exchange (</span><a href="http://3.bp.blogspot.com/-ZjYVRcm0t3k/TZimmFCtaAI/AAAAAAAAAX8/xMo9Gs6H_w0/s1600/2.gif" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-ZjYVRcm0t3k/TZimmFCtaAI/AAAAAAAAAX8/xMo9Gs6H_w0/s1600/2.gif" /></a>) and Conjunction to derive Modus Ponens. This is not the case in fuzzy logic; however, we can use the definition of d(x,y) and c(x,y) to make some significant inferences. In this example I will use additive logic, but it should easily be seen how to generalise this approach to any fuzzy logic.</div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">We have:</div><br /><span style="font-family: "Courier New",Courier,monospace;">1. P 43% Premise</span><br /><span style="font-family: "Courier New",Courier,monospace;">2. P -> Q 83% Premise</span><br /><br /><span style="font-family: "Courier New",Courier,monospace;"> </span><br /><div style="font-family: Georgia,"Times New Roman",serif;">And so we want to derive <i>Q</i>. we plug P's certainty value in for the formula we use for computing the certainty of disjunction:</div><br /><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;">d((1-p),q) = .83</span></span></span><br /><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;">d((1-.43),q) = .83</span></span></span><br /><br /><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;">We now substitute the particulars of <i>d(x,y)</i>. In our case, this is <i>min(1,x+y)</i>:</span></span></span></span><br /><br /><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;">min(1,1-.43+q) = .83</span></span></span><br /><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;">min(1,.57+q) = .83</span></span></span><br /><span style="font-family: "Courier New",Courier,monospace;"><span style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;"> </span></span></span><br /><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">It should be clear now that since <i>.83</i> is less than <i>1</i>, we know that <i>min(1,.57+q) = .57+q</i>. And so</div><br /><span style="font-family: "Courier New",Courier,monospace;">.57+q = .83</span><br /><span style="font-family: "Courier New",Courier,monospace;"> q = .26 .</span><br /><div style="font-family: Georgia,"Times New Roman",serif;">We can now attach <i>Q</i> to our proof above with certainty 26% under additive logic. </div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;">What if <i>P -> Q</i>'s value is 1 in this case? We find Q's certainty to be the least certainty that would give 1, adding 'greater than or equal to' next to it:</div><br /><span style="font-family: inherit;">1</span><span style="font-family: "Courier New",Courier,monospace;">. </span><span style="font-family: "Courier New",Courier,monospace;">P 83% Premise</span><br /><span style="font-family: "Courier New",Courier,monospace;">2. P -> Q 100% Premise</span><br /><span style="font-family: "Courier New",Courier,monospace;">3. Q 83% min(1,.27+q) = 1 :. smallest q = .83 .</span><br /><br /><div style="font-family: Georgia,"Times New Roman",serif;">That's how it works: <i>we use the formulas for d(x,y) and what we know about the certainty of the conditional and the antecedent, we can derive the certainty of the consequent.</i> </div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: large;">Conditional Proof</span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: small;">How do we create conditionals? Easy. Simply assume p to some certainty, derive q to some certainty, and then infer p -> q and assign a certainty value of d(1-p,q).</span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: small;">For example, under minimisation logic:</span></div><br /><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> 1. P 37% Assumption</span></span><br /><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> .</span></span><br /><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> .</span></span><br /><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;"> .</span></span><br /><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">17. Q 75% <some justification=""></some></span></span><br /><span style="font-size: small;"><span style="font-family: "Courier New",Courier,monospace;">19. P -> Q 75%</span></span><br /><br /><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: small;"><span style="font-size: large;">Contradiction<span style="font-size: small;"> </span></span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: small;"><span style="font-size: large;"><span style="font-size: small;">Although the law of contradiction does not apply <i>in general</i>, it applies at the "end points". In other words, if one can derive <i>p</i> with 100% certainty, and also <i>~q</i> to 100% certainty, its conjuction will (by definition) have 100% certainty, and one can obtain 0% certainty (100% certainty of the negation) and use this and conditional proof to prove something via <i>reductio ad absurdum</i>.</span></span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: small;"><span style="font-size: large;"><span style="font-size: small;"><span style="font-size: large;">Conclusion</span></span></span></span></div><div style="font-family: Georgia,"Times New Roman",serif;"><br /></div><div style="font-family: Georgia,"Times New Roman",serif;"><span style="font-size: small;"><span style="font-size: small;">This work was not intended as a comprehensive treatise on fuzzy logic inference rules, but hopefully I have provided in it a good feel for how it works. Enjoy! </span></span></div></div><div style="font-family: inherit;"></div><img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/Om3WtE33JwE" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2011/04/fuzzy-logic-iii-proof-construction.htmltag:blogger.com,1999:blog-4686393050407685865.post-5965207989495504042011-03-21T10:40:00.000-07:002011-03-22T13:37:38.938-07:00Fuzzy Logic Proofs II: Systems of LogicIn this post I will discuss how fuzzy logic works as opposed to conventional logic. This will lay groundwork for our discussion of fuzzy logic proofs later. Remember, the motivation for looking at such kinds of proofs is that it provides us with a means of dealing with uncertainty. Perhaps there are other motivations, but I will not mention them here.<br /><br />I assume basic knowledge of first order logic (and, or, not, only if, ...) and pretty much nothing else. Don't worry, I won't get all academic on you. We'll save that for papers and articles.<br /><br />Now there's a lot of theory and academic mumbo jumbo surrounding fuzzy logic, but practically speaking anyone can do it. A "fuzzy logic system" basically describes how to deal with "a & b (a AND b)", "a | b (a OR b)", and "~a (NOT a)" when we are, say, only 80% certain a is true and 50% certain b is true. There are two common ways of doing so that I will discuss here.<br /><br />Defining the last operation mentioned above is the easiest. no matter what kind of logic we use, "~a", the logical complement of a, is always going to be "1-a". This makes sense if look at conventional logic, taking 1 to be "True" and 0 to be "False":<br /><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://lh6.googleusercontent.com/-4X0WX0vFbKc/TYeAbNZ-V0I/AAAAAAAAAXU/sjCaEK97fcs/s1600/blog2.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://lh6.googleusercontent.com/-4X0WX0vFbKc/TYeAbNZ-V0I/AAAAAAAAAXU/sjCaEK97fcs/s1600/blog2.gif" /></a></div><br /><br /><span style="font-size: large;">Fuzzy Logic: Conservative Flavor</span><br /><br />The first is the most common. For "a & b", where a=.5 (50% certain) and b=.8 (80% certain) it says this: "Well, we know that a is 50% true, and b is more than 50% true, so we are at least 50% certain that the whole statement 'a & b' is true." This conservative attitude contributes to its popularity, and the fact that we take the smallest certainty value to be the value of the whole statement gives it a name: <i>minimization</i> fuzzy logic. So the certainty of the expression "a & b" is the smallest of the two between a and b. You may note that this works for conventional logic:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-mkI-Q9qXryc/TYd8R6yATeI/AAAAAAAAAXQ/uF-iJUd7uVM/s1600/blog1.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://lh3.googleusercontent.com/-mkI-Q9qXryc/TYd8R6yATeI/AAAAAAAAAXQ/uF-iJUd7uVM/s1600/blog1.gif" /></a></div>as for "a | b", we use DeMorgan's Law to define the meaning of disjunction. As "a | b" is equivalent to "~(~a & ~b)", we can just use subtraction and "min" to find out our OR operation. It turns out that the certainty of the statement "a | b" turns out to be the greatest value between a and b. This matches our conservative intuition: "We know a 50% true and b is 80% true, so 'a | b' must be at least 80% true." This is again confirmed by using our conventional "absolute truth" model:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://lh3.googleusercontent.com/-QxtXN8Adn04/TYeB3h6BdvI/AAAAAAAAAXY/7BVKMjuMeug/s1600/blog3.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://lh3.googleusercontent.com/-QxtXN8Adn04/TYeB3h6BdvI/AAAAAAAAAXY/7BVKMjuMeug/s1600/blog3.gif" /></a></div>Furthermore, with this (and many other) systems of fuzzy logic, the conventional laws of association, commutation, and transititivity still apply, as well as our faithful friend, DeMorgan's Laws.<br /><br />Although not generally true of fuzzy logic (though totally true in conventional logic), minimization logic follows the law of idempotence; in other words, <br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://lh5.googleusercontent.com/-_kiiwXgivA4/TYeFSSlMuKI/AAAAAAAAAXk/c8Pnrm7LqXE/s1600/blog4.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://lh5.googleusercontent.com/-_kiiwXgivA4/TYeFSSlMuKI/AAAAAAAAAXk/c8Pnrm7LqXE/s1600/blog4.gif" /></a></div><br /><span style="font-size: large;">Fuzzy Logic: Liberal Flavor</span><br /><br /><span style="font-size: large;"><span style="font-size: small;">No pun intended, by the way, in the naming of these flavors. They're both important for our purposes, and the usefulness and limits of each will be demonstrated.</span></span><br /><br /><span style="font-size: small;">All the cool stuff except idempotence (association, commutation, transitivity, etc.) apply to this logic as well, including the fact </span><span style="font-size: small;">that this kind of logic works with conventional logic (it works using only the values 0 and 1). </span><br /><br /><span style="font-size: small;">The next flavor of logic is actually defined, not by its conjunction operation (AND), but by its disjunction (OR). For example, let's say that we know x is 40% true and y is 30%. To figure out how to assign a certainty value to the phrase 'x | y', we simply add their certainties together; therefore, 'x | y' has a certainty value of 70%. </span><br /><br /><span style="font-size: small;"><i>Wait!</i> <i>what if y was 70% certain? then 'x | y' would be 110% certain!?!?</i> </span><br /><br /><span style="font-size: small;">Nah. We'll just say that if the certainty of x and y sum to more than 1 (or just barely made it to one), the couple has "made the cut" and we say that their combined certainties are more than enough to make us certain that 'x | y' is absolutely true. therefore, If the certainty of x and y are 40% and 80%, 'x | y' is still 1. That's why this logic system is referred to as <i>bounded addition</i>. We see that this flavor of logic is quite liberal - It takes the certainty of BOTH values into the value of the whole. </span><br /><br /><span style="font-size: small;">Using DeMorgan's Laws, we use NOT and OR to find AND. Conjuction (AND) here has the same kind of "make the cut" attitude: "If x and y's certainties sum to more than one, it's significant. Otherwise, we really can't say much about the certainty of 'x & y' as a statement." In other words: take the certainties of x and y, subtract 1, and you have the value of 'x & y'. Again the question arises, "What if x and y are at 0%?" The answer is in the same spirit as last time. if x+y-1 is less than 0, we'll just interpret that as we are so uncertain of x and y that we have more than enough reason simply to assign the certainty of truth for 'x & y' to be false. </span><br /><br /><span style="font-size: small;">This is also called </span><a href="http://en.wikipedia.org/wiki/%C5%81ukasiewicz_logic">Łukasiewicz (Loo-KAH-she-vich) logic</a>, after <a href="http://en.wikipedia.org/wiki/Jan_%C5%81ukasiewicz">the polish philosopher</a> who first invented fuzzy logic. Yes, ladies and gentlemen - additive logic was the first fuzzy logic out there, invented near the turn of the 20th century.<br /><br />This logic is cool over other logics because unlike most other logics, Łukasiewicz logic obeys contradiction and excluded middle laws:<br />"a & ~a"=0%, "a | ~a"=100%. <br /><br /><i>What? MOST fuzzy logic doesn't obey contradiction? How can people use minimization logic without it? How can MODUS PONENS even work without it?</i><br /><br />Oh, but it can. I'll show you how next time. (I said in my first post that I'd save that stuff for my third post, not my second, but I think I'll just jump to the good stuff.)<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/PSOXPLV80Ek" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2011/03/fuzzy-logic-proofs-ii-systems-of-logic.htmltag:blogger.com,1999:blog-4686393050407685865.post-32237548614130321062011-03-18T12:33:00.000-07:002011-03-18T12:33:10.672-07:00Fuzzy Logical ProofsMany decent EE Professors will tell you that Fuzzy Logic is used quite a bit in fuzzy control. For those of you who don't know what that is, congratulations; you're a member of normal society. We will not dwell on that here. Instead, we will focus these Fuzzy Logic energies into logical proofs.<br /><br />For those logicians out there familiar with normal two-column proofs, such as fitch-style natural deduction proofs or similiar, you will find this somewhat familiar. The difference between fuzzy proofs and conventional proofs is that fuzzy proofs provides us a mechanism to deal with uncertainty.<br /><br />In conventional First Order Logic, we may for any given statement assign a truth value out of the set of two truth values, True and False. In Fuzzy Logic, there is a "spectrum of truth" wherein a statement can be "20% True" and "80% False". Another (more intuitionistic) interpretation of such a value in terms of using it to form a proof is that we are 20% certain that value A is true. Thus fuzzy proofs allow us to use premises with varying degrees of certainty, and in a chosen interpretation allow us to prove results, perhaps even with higher degrees of certainty than our premises. (Side note: those of you familiar with Zadeh's work may cringe at this, but I will explain what I mean when we get there.)<br /><br />This post starts a series of blog posts which I will publish on the subject of Fuzzy Proofs as I understand them. Please feel free to make comments and give criticisms for my arguments. <br /><br />In the first post we will define what "fuzzy logic" herein means, and explore the possibilities of the different logical systems at our disposal, and why we may or may not choose them for our proof or to solve a specific problem. Feedback will be requested here. This is a domain which I am trying to understand better even now.<br /><br />In the second post we will define what an "interpretation" is, or in other words, we will define how to translate our mathy proof back into english so that it may be used to make decisions, as all useful proofs must ultimately provide use for this end.<br /><br />In the last post, we will walk through a sample fuzzy logic proof. I will comment on its usefulness, its form, and its weaknesses.<br /><br />From what I can understand, this field has only been explored by few scholars, most deeming it of little use. But I find it relevant here to examine G. H. Hardy, who said "I have never done anything useful," thinking number theory to be an unimportant part of mathematics. Without him, RSA would not be where it is today. (re-quoted from <i>Algorithms,</i> by S. Dasgupta, C.H. Papadimitriou, and U.V. Vazirani, p. 41.)<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/Z8_AovGF4jY" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2011/03/fuzzy-logical-proofs.htmltag:blogger.com,1999:blog-4686393050407685865.post-1034029503165280582010-06-20T09:03:00.000-07:002010-06-20T09:33:39.405-07:00'Illegals'As far as I can tell, the 'problem' with illegal aliens that people have beef with is<br />1) they don't pay taxes.<br />2) they aren't citizens.<br />3) they steal jobs from americans and then send the money back home to mexico.<br /><br /><br />As far as I can tell, the problem with giving them citizenship in a reasonable way (and a way fair to those who took a while to get it) is two fold:<br />1) the laws on the books only allow 'skilled' workers to gain citizenship and<br />2) the government likes to turn a blind eye to the issue, because when things are good, they can pretend our illegals from down south are citizens to aid the business who hire them, and they can point the finger at the illegals when a crisis breaks out or the economy takes a downturn, like it did some years back and eyes turned once again to illegals, whom we treated as scape goats, saying 'we want our jobs back' when indeed, when the economy was good, we wanted better jobs than what they had. The government likes to turn a blind eye when our economy goes well for another reason: to help businesses. the reader will note that <span style="font-weight: bold;">it is illegal to be an illegal, but it's not illegal to hire them. </span><br /> Many point the finger at the illegal, but shouldn't we also point the finger at the government for allowing such a loop hole to take place? <span style="font-weight: bold;">This allows businesses to favor illegals, because they can pay illegals next to nothing, and if the illegal doesn't have to pay taxes and social security, then neither does the business. </span>People often forget that businesses have to pay social security every time we do. Why haven't we fixed this yet? <span style="font-weight: bold;">It should be illegal to hire an illegal.</span><br /> On the other side of the coin, 'unskilled' workers should be able to gain citizenship along with 'skilled' workers (people with a degree). When it comes right down to it, Mexicans are better and more willing to do 'unskilled' jobs then we are.<br />My wife worked in the hotel industry for a number of years. when they were hiring for housekeeping, whites would come in and only ask for desk jobs. they were not interested in the laundry, dusting and cleaning that the mexicans hired there were so proficient at. when they were hired on at those jobs, my wife me, they had a hard time keeping up. On my mission, a cherry farmer told me that it was taking longer for his crop to get harvested 'because quite frankly, there are fewer migrant workers getting over the border.' And when I served in Stevenson, WA, I lived with a man who owned a landscaping company. after research and reading different magazine articles and, eventually, by his own experience, he came to the conclusion that he should hire a mexican over a white american because, he said,<span style="font-weight: bold;"> they work harder and are 10 times more productive than the average white. </span>He said that<span style="font-weight: bold;"> if he wanted to keep up in his market place, he needed to hire a mexican.</span><br /> Hearing and seeing all this has lead me to believe that 'unskilled' work takes alot more skill than meets the eye. I think there should be legislation allowing these hard workers to gain citizenship in the same manner which skilled workers can obtain it. Think of all the mexican illegals working today - imagine if they were eventually all made citizens. <span style="font-weight: bold;">The tax dollars rolling in would help America.</span> Think of it. If mexicans saw light at the end of the tunnel for their citizenship, they would move their family up with them once they got it to the states. <span style="font-weight: bold;">Therefore, they would no longer be sending money out of the US to support their families, and their families would spend that money here in the states.</span> being citizens (like they want to be), they would pay taxes, not to mention that the businesses that hired them would have to pay the taxes they needed to pay as well, while still being able to hire these excellent workers. The hard truth is that mexicans desiring citizenship should be given it as easily as anyone else. this is admittedly not easy, but right now it is nearly impossible.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/6TOR-_Xrolw" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2010/06/illegals.htmltag:blogger.com,1999:blog-4686393050407685865.post-52046369915632780512010-06-20T09:01:00.000-07:002010-06-20T09:03:39.362-07:00An opinion or two.I've started this blog to share some things I feel are important to share with the world. I probably won't post alot, I generally have no problem just feeling what I'm feeling to myself or my wife. But sometimes I feel like I want to share an experience or an opinion that I feel others should hear.<img src="http://feeds.feedburner.com/~r/blogspot/FaFWU/~4/HMDD8EbU7Bs" height="1" width="1" alt=""/>Daniel Haskinhttps://plus.google.com/115484109589467353726noreply@blogger.com0http://djhaskin987.blogspot.com/2010/06/opinion-or-two.html