<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-35677212</id><updated>2011-07-07T18:50:53.593-05:00</updated><title type='text'>The Zen of Jess</title><subtitle type='html'>A blog devoted to the application of Jess technology.  If you are a practical Jess programmer, this blog is for you.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-35677212.post-5151875738382204614</id><published>2009-03-28T03:53:00.005-05:00</published><updated>2009-03-28T04:28:40.537-05:00</updated><title type='text'>Using Enums in Jess Patterns</title><content type='html'>As Wolfgang Laun and Scott &lt;span class="sender"&gt;Krasnigor &lt;/span&gt;have mentioned on the &lt;a href="http://www.mail-archive.com/jess-users@sandia.gov/msg09593.html"&gt;Jess list&lt;/a&gt;, you can indeed use enums in your Jess rule patterns.  The trick is that if you look at the way enums work in Java 1.5 and beyond, accessing the enumeration type is a function call.  To match a slot on the return value of a function call, you have to use Jess's &lt;span style="font-style: italic;"&gt;return value constraint&lt;/span&gt; (=).&lt;br /&gt;&lt;br /&gt;Figure 1 shows a pseudo-code example.&lt;br /&gt;&lt;br /&gt;&lt;div style="border: 2px solid rgb(40, 119, 148); background-color: rgb(231, 249, 255);"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(slot-name =(EnumType.enumConstant))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Figure 1.  Using enums in Jess patterns.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In &lt;a href="http://zen-of-jess.blogspot.com/2009_01_01_archive.html"&gt;SINFERS&lt;/a&gt;, our rules get a bit more sophisticated.  Figure 2 shows the LHS of the rule that proposes &lt;span style="font-style: italic;"&gt;candidate &lt;/span&gt;computations of the amount of exchangeable calcium (Ca++) ions as a function of the the amount of exchangeable bases, soil pH, and the percentage of clay in a soil sample.&lt;br /&gt;&lt;br /&gt;&lt;div style="border: 2px solid rgb(40, 119, 148); background-color: rgb(231, 249, 255);"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;(defrule PROPOSE::ptf__15F1_CA_11&lt;br /&gt;"Proposes _15F1_CA_11 as best candidate to compute _15F1_CA"&lt;br /&gt;(not (MAIN::SoilProperty (labCode "_15F1_CA" ) (state =(SoilPropertyStateType.COMPUTED))))&lt;br /&gt;(MAIN::SoilProperty&lt;br /&gt;(labCode "_15F1_CEC")&lt;br /&gt;(state =(SoilPropertyStateType.INITIAL)|=(SoilPropertyStateType.COMPUTED))&lt;br /&gt;(uncertainty ?e1)&lt;br /&gt;(value ?v1)&lt;br /&gt;(OBJECT ?objSp1))&lt;br /&gt;&lt;br /&gt;(MAIN::SoilProperty&lt;br /&gt;(labCode "_4A1")&lt;br /&gt;(state =(SoilPropertyStateType.INITIAL)|=(SoilPropertyStateType.COMPUTED))&lt;br /&gt;(uncertainty ?e2)&lt;br /&gt;(value ?v2)&lt;br /&gt;(OBJECT ?objSp2))&lt;br /&gt;&lt;br /&gt;(MAIN::SoilProperty&lt;br /&gt;(labCode "_P10_NR_C")&lt;br /&gt;(state =(SoilPropertyStateType.INITIAL)|=(SoilPropertyStateType.COMPUTED))&lt;br /&gt;(uncertainty ?e3)&lt;br /&gt;(value ?v3)&lt;br /&gt;(OBJECT ?objSp3))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Figure 2.  A real world example from SINFERS.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The pattern matches if we see &lt;span style="font-family:courier new;"&gt;sinfers.core.SoilProperty&lt;/span&gt; objects (as shadow facts) that are either INITIAL (meaning they were part of the input set) or COMPUTED (meaning they have survived candidacy, and are now authoritative sources of data for this computed property).&lt;br /&gt;&lt;br /&gt;Add this powerful pattern-matching technique to your Jess toolbox!  -JM&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-5151875738382204614?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/5151875738382204614/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=5151875738382204614' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/5151875738382204614'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/5151875738382204614'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2009/03/using-enums-in-jess-patterns.html' title='Using Enums in Jess Patterns'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35677212.post-1065396000888046105</id><published>2009-03-27T21:52:00.028-05:00</published><updated>2009-03-28T04:54:10.374-05:00</updated><title type='text'>Application Scripting with the Jess Language</title><content type='html'>Early on in my running example, the &lt;a href="http://zen-of-jess.blogspot.com/2009_01_01_archive.html"&gt;SINFERS &lt;/a&gt;soil property expert system that I've been working on for 2+ years now, we encountered the need for a console user interface to drive our prototype during testing and to give proof-of-concept demos.&lt;br /&gt;&lt;br /&gt;Arguably, there are many ways to skin this cat (sorry PETA folks!), but what is the quickest and easiest?  What is simple enough to meet the immediate need, but also scalable should we decide to keep it?  Given our time constraints, we don't have the luxury of expendable code.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Rejected Approaches&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The first thought was to write a command line parser in ANTLR, but this was quickly determined not to be worth the time and effort involved since it would require rather special knowledge of ANTLR to maintain and expand.&lt;br /&gt;&lt;br /&gt;Second, we looked at using the Jython language, since the Jython API includes the &lt;span style="font-family:courier new;"&gt;org.python.util.PythonInterpreter&lt;/span&gt; class for embedding Jython scripting in a Java application and since we were already using Jython for doing automated rule generation from our pedotransfer function database.  This worked well for driving the SINFERS API for a while, but that meant that we'd have to depend on later developers knowing Java, Jython, and Jess.  What we really needed was transparent access to SINFERS and Jess via a command line, keeping dependencies on other libraries to a minimum.&lt;br /&gt;&lt;br /&gt;Then a crazy idea occurred to me:  Just use Jess!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Jess as a General Purpose Scripting Language&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Like Dorothy, I had had the power to go back to Kansas all along, &lt;span style="font-style: italic;"&gt;I just didn't see it&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The reason is simple: 99% of the time, I use the Jess language for the mundane tasks of scripting rules, defining modules, deftemplates, and all the other constructs and initialization stuff -- all as you're supposed to do.  However, the Jess language is much more that just a driver of the Jess API, &lt;span style="font-style: italic;"&gt;it can script the Java language itself&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;As Ernest is want to say, "&lt;span style="font-style: italic;"&gt;Anything that you can do with Java you can do with Jess&lt;/span&gt;."&lt;br /&gt;&lt;br /&gt;Now, one of the neat things about Jess is that is extremely easy to add new functionality.  All you have to do to add a function to Jess is create a new command class that implements the &lt;span style="font-family:courier new;"&gt;jess.Userfunction &lt;/span&gt;interface.  For greater convenience, these functions can be loaded via a &lt;span style="font-family:courier new;"&gt;jess.Userpackage&lt;/span&gt; class during application initialization.&lt;br /&gt;&lt;br /&gt;This is great if you want to call new, custom functions from Jess script during debugging and general development, &lt;span style="font-style: italic;"&gt;but what if Jess is acting as an embedded component in a larger system? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;What we decided to do was to create a number of commands classes implementing the &lt;span style="font-family:courier new;"&gt;jess.Userfunction&lt;/span&gt; interface, add them to a userpackage, and make the userpackage an internal implementation detail of the SINFERS API.  This gives us a simple and robust means of adding commands to SINFERS.   The &lt;span style="font-family:courier new;"&gt;sinfers.core.commandsCmdImportModel&lt;/span&gt; class is shown in Figure 1 as an example.&lt;hr /&gt;&lt;br /&gt;&lt;div style="border: 2px solid rgb(15, 78, 101); background-color: rgb(231, 249, 255);"&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;public class CmdImportModel implements Userfunction {&lt;br /&gt;&lt;br /&gt;public Value call(ValueVector vv, Context context) throws JessException {&lt;br /&gt;   String successMessage = null;&lt;br /&gt;   log.debug("CALLING COMMAND: import-model...");&lt;br /&gt;   Object obj = vv.get(1).javaObjectValue(context);&lt;br /&gt;   Rete engine = context.getEngine();&lt;br /&gt;   Object model = null;&lt;br /&gt;   Sinfers sinfers = (Sinfers) (engine.fetch("SINFERS")&lt;br /&gt;           .javaObjectValue(context));&lt;br /&gt;   if (obj instanceof java.io.File) {&lt;br /&gt;       File f = (File) obj;&lt;br /&gt;       model = sinfers.importModel(f);&lt;br /&gt;       try {&lt;br /&gt;            successMessage = "Model imported from " + f.getCanonicalPath() + " OK!";&lt;br /&gt;       } catch (IOException e) {&lt;br /&gt;           log.error("Model imported failed!  Could not find canonical file path.");&lt;br /&gt;           e.printStackTrace(System.err);&lt;br /&gt;       }&lt;br /&gt;   } else if (obj instanceof java.net.URL) {&lt;br /&gt;       URL url = (URL) obj;&lt;br /&gt;       model = sinfers.importModel(url);&lt;br /&gt;        successMessage = "Model imported from " + url.toString() + " OK!";&lt;br /&gt;   } else if (obj instanceof java.lang.String) {&lt;br /&gt;       String s = (String) obj;&lt;br /&gt;       model = sinfers.importModel(s);&lt;br /&gt;       successMessage = "Model imported from " + s + " OK!";&lt;br /&gt;   } else {&lt;br /&gt;       log.debug("Unrecognized argument to import-model command.");&lt;br /&gt;       throw new JessException(&lt;br /&gt;               "Unrecognized argument to import-model command", null, 0);&lt;br /&gt;   }&lt;br /&gt;   log.debug("Model imported OK.");&lt;br /&gt;   System.out.println(successMessage);&lt;br /&gt;   return new Value(model);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public String getName() {&lt;br /&gt;   return "import-model";&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;&lt;span style="font-family:georgia;"&gt;Figure 1.  The SINFERS CmdImportModel class.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Just as Jess has a &lt;span style="font-family:courier new;"&gt;Main &lt;/span&gt;class, so to does SINFERS, which drives an instance of the &lt;span style="font-family:courier new;"&gt;sinfers.main.Sinfers&lt;/span&gt; class. &lt;span style="font-family:courier new;"&gt; Sinfers &lt;/span&gt;is the true application class in the SINFERS API - a facade much like the &lt;span style="font-family:courier new;"&gt;Rete &lt;/span&gt;class in the Jess API.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-family:courier new;"&gt;Rete &lt;/span&gt;method &lt;span style="font-family:courier new;"&gt;eval()&lt;/span&gt; is able to parse and execute functional expressions.  So, since each userfunction fits that description, we can pass our SINFERS commands to Jess from the console and have them executed by &lt;span style="font-family:courier new;"&gt;Rete.eval()&lt;/span&gt;.  The net effect is that Jess is scripting our API, giving us the ability to run either one SINFERS commands or Jess's commands at the SINFERS command line.&lt;br /&gt;&lt;br /&gt;Figure 2 shows the result of having imported one of our soil property data files for analysis. Note the seamless extension with Jess proper.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GpzkbrexfHA/Sc3TxoY9lPI/AAAAAAAAACQ/8S-wp58B5c8/s1600-h/SINFERS_console.gif"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 400px; height: 247px;" src="http://3.bp.blogspot.com/_GpzkbrexfHA/Sc3TxoY9lPI/AAAAAAAAACQ/8S-wp58B5c8/s400/SINFERS_console.gif" alt="" id="BLOGGER_PHOTO_ID_5318139584603591922" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Figure 2.  Using Jess to provide a simple, embedded, command line interface.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Of course, I could have hacked Jess's source to change the prompt and all that, but the problem is more than cosmetic.  Among other things, we wanted to reserve the right to pass arguments, expressions, and switches on the command line that Jess &lt;span style="font-family:courier new;"&gt;eval()&lt;/span&gt; cannot accept.  [&lt;span style="font-style: italic;"&gt;I suppose I could just add more userfunctions for these special cases too, eh? -JM]&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The really cool thing is that the Rete instance that is powering the SINFERS command line in this session is the same instance that this session uses for its inferencing -- Jess is pulling double duty!  But it gets cooler!  Can SINFERS run a script of its commands?  You bet!  Jess doesn't care.  Just like writing any CLP file of Jess code, I can mix and match SINFERS commands with native Jess commands for true shell scripting.  See Figure 3 for an example script.&lt;br /&gt;&lt;br /&gt;&lt;div style="border: 2px solid rgb(15, 78, 101); background-color: rgb(231, 249, 255);"&gt;&lt;br /&gt;&lt;pre&gt;;; test.clp&lt;br /&gt;;; ========&lt;br /&gt;;; Imports and analyzes a SINFERS model file.&lt;br /&gt;(watch all)&lt;br /&gt;(bind ?model (import-model "simpleModel.xml"))&lt;br /&gt;(add-model ?model)&lt;br /&gt;(run-sinfers)&lt;br /&gt;(facts *)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;Figure 3.  A SINFERS script file.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As far as I know, this is a novel way of exploiting the power of the Jess language to control the API of a host application. - JM&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-1065396000888046105?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/1065396000888046105/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=1065396000888046105' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/1065396000888046105'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/1065396000888046105'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2009/03/application-scripting-with-jess.html' title='Application Scripting with the Jess Language'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_GpzkbrexfHA/Sc3TxoY9lPI/AAAAAAAAACQ/8S-wp58B5c8/s72-c/SINFERS_console.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35677212.post-5348511484451814606</id><published>2009-02-14T18:28:00.021-05:00</published><updated>2009-02-15T00:19:48.520-05:00</updated><title type='text'>The Zen of Jess 2009:  Part II</title><content type='html'>by Jason Morris&lt;br /&gt;&lt;br /&gt;In Part I, we said that for many new Jess users, declarative programming will be a completely alien paradigm that warrants a careful and thoughtful study before attempting to write serious code.  The following steps are a practical checklist that will greatly facilitate your Jess study.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;1. Get the latest Jess code.&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;Go to &lt;a href="http://www.jessrules.com/jess/"&gt;http://www.jessrules.com/jess/&lt;/a&gt; and install the latest binary version of Jess (jess.jar) or the whole JessDE if you're using Eclipse. Updating old versions will help you avoid fixed bugs incompatibility issues.  Jess runs very well on the latest Ganymede (3.4.x) releases of Eclipse.&lt;br /&gt;&lt;br /&gt;If you pose a question on the Jess list server and you’re running an old version, the very first thing you will be asked to do is update your code.  Don’t expect that code that you wrote on an ancient version of Jess will run with the latest version, although we will certainly help you try to migrate if we can.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;NOTE:&lt;/span&gt;  I wouldn’t use anything else but the JessDE for my Jess development.  Editors like JessWin were developed by a third-party and are not supported by the Jess team.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.manning.com/friedman-hill"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 200px; height: 300px;" src="http://3.bp.blogspot.com/_GpzkbrexfHA/SZddvXLMJVI/AAAAAAAAABY/jBp8K_yIPlk/s320/jia_cover_50%25.jpg" alt="" id="BLOGGER_PHOTO_ID_5302810154508232018" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;2. Study the online documentation.&lt;/span&gt;&lt;br /&gt;You'll want to keep a link to &lt;a href="http://www.jessrules.com/jess/docs/71/table_of_contents.html"&gt;http://www.jessrules.com/jess/docs/71/table_of_contents.html&lt;/a&gt; as your current background reference on Jess. The Jess manual still provides the single best overview of how Jess functionality is structured. Dr. Friedman-Hill is dedicated to keeping this document up-to-date and full of relevant examples. This is a manual, not a textbook, so there is no fluff or extraneous filler.&lt;br /&gt;&lt;br /&gt;The current table of contents has 22 chapters:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Chapters 1 through 11 are essential reading.    &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Chapters 12 through 15 are advanced topics that you can visit once you have mastered the basics.  &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Chapters 16 through 18 are essential reference links that you will need at all times.  Chapters 19 through 22 are various appendices.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;One unfortunate thing about the online HTML docs is that they are not searchable.  So, I would also keep a link to the PDF version, too &lt;a href="http://www.jessrules.com/jess/docs/Jess71p2.pdf"&gt;http://www.jessrules.com/jess/docs/Jess71p2.pdf&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The HTML docs really need a better index.  Perhaps I can whip up a Microsoft Compiled Help File (*.chm) for the Jess docs?  How about a Java help version, too?&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_GpzkbrexfHA/SZelgWdcPMI/AAAAAAAAABo/Z9qN-BGib0s/s1600-h/JessToolbar.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 153px; height: 320px;" src="http://3.bp.blogspot.com/_GpzkbrexfHA/SZelgWdcPMI/AAAAAAAAABo/Z9qN-BGib0s/s320/JessToolbar.jpg" alt="" id="BLOGGER_PHOTO_ID_5302889061455510722" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;3. Create reference shortcuts on your desktop.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;I recommend making desktop shortcuts to the following pages:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.jessrules.com/jess/docs/70/function_index.html"&gt;http://www.jessrules.com/jess/docs/70/function_index.html &lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.jessrules.com/jess/docs/71/constructs.html#"&gt;http://www.jessrules.com/jess/docs/71/constructs.html#&lt;/a&gt;&lt;br /&gt;&lt;a href="http://www.jessrules.com/jess/docs/71/api.html#"&gt;http://www.jessrules.com/jess/docs/71/api.html#&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;4. Purchase a copy of Jess In Action (JIA).&lt;/span&gt;&lt;br /&gt;JIA &lt;a href="http://www.manning.com/friedman-hill"&gt;http://www.manning.com/friedman-hill&lt;/a&gt; by Jess's author, Dr. E. Friedman-Hill, will be your main tutorial and primer on how to program in Jess. Its ISBIN code is 1930110898. Mine is "dog-eared" and annotated already from use – I honestly don’t know what is holding it together anymore. Eat, sleep, and breathe chapters 1 through 7 – know them like a Marine knows his rifle. Try everything at the Jess command line using the Jess language first.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;I recommend not trying to program the Jess API directly until you do this step.  &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Why&lt;/span&gt;?  Because you will learn the value of what should be done using the Jess language versus using the Jess API this way.&lt;br /&gt;&lt;br /&gt;You can see my full Amazon review at&lt;br /&gt;&lt;a href="http://www.amazon.com/exec/obidos/tg/detail/-/1930110898/"&gt;http://www.amazon.com/exec/obidos/tg/detail/-/1930110898/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;5. Work the JIA tutorials.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Now, once you have a grasp of the Jess language, try the tutorials in JIA (chapters 8 and beyond), and type the code samples into Jess so that you can see how they work. Experimental learning is the key with Jess – take advantage of the fact the Jess language is interpreted to get that immediate feedback. It's very gratifying to write a little code snippet that gives you insight into a larger example.&lt;br /&gt;&lt;br /&gt;Some variations on the &lt;span style="font-style: italic;"&gt;what if&lt;/span&gt;? theme that worked for me:&lt;br /&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Writing many, small deffunctions that print something or calculate something.&lt;/span&gt;&lt;br /&gt;This is a great way to practice using Jess's variables and list-based syntax. Practice taking apart and creating lists and multifields. Remember that lists don't just hold primitives, they can hold object references as well.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Changing the behavior of a JIA snippet.&lt;/span&gt;&lt;br /&gt;If an example writes output to the console, change it to write to a file. If a defquery looks for all (foo (color ?c)) facts, make it look for all (foo (color blue)) facts, or any non-blue foo facts (foo (color ~blue)). &lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Experiment with LHS patterns.&lt;/span&gt;&lt;br /&gt;Get a little fact-base built with some simple rules and modify the rule LHS patterns a bit after each run. Try all the different pattern constraints (this takes time, but pays huge dividends later). Avoid the performance traps of bad pattern ordering on your LHS of rules. &lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;font-size:100%;" &gt;6. Participate on the Jess Mailing List and Jess Wiki &lt;/span&gt;&lt;br /&gt;Bar none, the atmosphere at the Jess list server is one of the friendliest and most supportive on the internet.  New Jess users do not have to fear the condescending replies and otherwise inappropriate remarks that mar so many other IT forums and email lists.&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Jess List Server Etiquette &lt;/span&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_GpzkbrexfHA/SZdcEa_OTYI/AAAAAAAAABQ/3m20zPuljQ0/s1600-h/huh_50%25.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 179px; height: 320px;" src="http://1.bp.blogspot.com/_GpzkbrexfHA/SZdcEa_OTYI/AAAAAAAAABQ/3m20zPuljQ0/s320/huh_50%25.jpg" alt="" id="BLOGGER_PHOTO_ID_5302808317285780866" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;1. Read the documentation.  &lt;/span&gt;&lt;br /&gt;Make sure that you have read the Jess documentation most relevant to your question before you post your question.  By doing this, you help eliminate the most likely problems and increase the likelihood of finding a solution on your own which is always very satisfying.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2. Be specific. &lt;/span&gt;&lt;br /&gt;When you ask a question about the behavior of some code, give the actual code snippet that is causing the problem, not just a word description of it.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;3. Explain your purpose.  &lt;/span&gt;&lt;br /&gt;Tell us what you are trying to do or what result you want to have.  Very often, we can suggest a better or more correct way than what you have already coded.&lt;br /&gt;&lt;br /&gt;You can join the mailing list at:&lt;br /&gt;&lt;a href="http://www.jessrules.com/jess/mailing_list.shtml"&gt;http://www.jessrules.com/jess/mailing_list.shtml&lt;/a&gt;&lt;br /&gt;or participate on the Jess Wiki at:&lt;br /&gt;&lt;a href="http://www.jessrules.com/jesswiki/view"&gt;http://www.jessrules.com/jesswiki/view&lt;/a&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;As for posting on the list server, don't be afraid to ask questions, but do try to exhaust the obvious causes of errors before posting -- you learn more that way. I strongly encourage you to try to replace all questions of the form &lt;span style="font-style: italic;"&gt;How do I&lt;/span&gt;...?, &lt;span style="font-style: italic;"&gt;How can I&lt;/span&gt;…? with a simple experimental code snippet.&lt;br /&gt;&lt;br /&gt;Here's an example: Instead of asking "&lt;span style="font-style: italic;"&gt;How do I make Jess switch from one module to the next?&lt;/span&gt;", I'd first read a bit about using (focus), then I'd write a little test like&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;font-size:85%;"  &gt;;; test_focus.clp&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(clear)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;font-size:85%;"  &gt;;; Using a fact as a trigger is perfectly acceptable&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(deftemplate MAIN::switch-to (slot module-name))&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;font-size:85%;"  &gt;;; Make a rule that looks for this pattern&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(defrule MAIN::switch-module&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(MAIN::switch-to (module-name ?name))&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;=&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;font-size:85%;"  &gt;;; Show me what's happening&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(watch all)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;font-size:85%;"  &gt;;; Hypothesize here... what do you think will happen?&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(focus ?name))&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;font-size:85%;"  &gt;;; Need a place to switch to!&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(defmodule FOO)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-family:courier new;font-size:85%;"  &gt;;; A friendly confirmation that we made it OK&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(defrule FOO::executing-in-foo&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;=&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(printout t "Switched to module FOO!" crlf))&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(reset)&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;(assert (switch-to (module-name FOO)))&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-size:85%;"&gt;(run)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;... and Jess will print out&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;== Focus MAIN &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;==&gt; Focus FOO&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;FIRE 2 FOO::executing-in-foo f-0&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;Switched to module FOO!&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;== Focus FOO ==&gt; Focus MAIN&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;&lt;== Focus MAIN 2 &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=";font-family:courier new;font-size:85%;"  &gt;Jess&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Experimenting like this is very serendipitous. One thing that you might notice is that focus returned to the MAIN module automatically when no further rules in the FOO module were activated. You can imagine that doing many, many little such exercises will really boost your Jess understanding. Eventually, when you move beyond trivial examples to real applications, you'll have a whole toolbox of techniques with which to construct your Jess code.&lt;br /&gt;&lt;br /&gt;So, when I'm faced with a tough bug, I ask myself, "&lt;span style="font-style: italic;"&gt;Ok...what's Ernest going tell me&lt;/span&gt;?", and I dig deeper and usually find the answer on my own. Infinitely more satisfying and more educational! If you do discover a useful approach or novel technique, by all means, share it on the Jess Wiki!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GpzkbrexfHA/SZdk56IjZDI/AAAAAAAAABg/Dg-DtSvk5Po/s1600-h/pelosi_jess.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 220px; height: 320px;" src="http://4.bp.blogspot.com/_GpzkbrexfHA/SZdk56IjZDI/AAAAAAAAABg/Dg-DtSvk5Po/s320/pelosi_jess.jpg" alt="" id="BLOGGER_PHOTO_ID_5302818032272499762" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;7. Keep a programmer's journal.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;As you experiment and construct your own Jess knowledge, you will accumulate your own tips, tricks, and best-practices. Veteran programmers do this religiously. I continue to have many little epiphanies as I create course content, program my own applications, and study new materials, and you'll want to record your thoughts and discoveries, too. Again, if you can share your learning experiences on the Jess Wiki, that would be great!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;8. Review some LISP and some CLIPS.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Learning LISP is to learning CLIPS and Jess what learning Latin is to learning English -- it will give you a better sense of where certain concepts originated and help you with the list-based syntax.&lt;br /&gt;&lt;br /&gt;CLIPS is the inspiration for Jess, and Jess owes a good deal of its syntax to CLIPS. Therefore, much (but not all) of what you see in CLIPS is similar to Jess.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Expert Systems: Principles and Programming 4th Ed&lt;/span&gt;, by Giarratano &amp;amp; Riley, is a good companion volume to JIA for reviewing CLIPS syntax, and it will reinforce your study of Jess. For Common LISP, there is the very good and FREE online reference &lt;a href="http://www.gigamonkeys.com/book/"&gt;http://www.gigamonkeys.com/book/ &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;All of these techniques are helpful, but in order to really put them into practice, you have to first study what tools like Jess are meant to do.&lt;br /&gt;&lt;br /&gt;We’ll tackle this in Part III. - JM&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-5348511484451814606?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/5348511484451814606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=5348511484451814606' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/5348511484451814606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/5348511484451814606'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2009/02/zen-of-jess-2009-part-ii.html' title='The Zen of Jess 2009:  Part II'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_GpzkbrexfHA/SZddvXLMJVI/AAAAAAAAABY/jBp8K_yIPlk/s72-c/jia_cover_50%25.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35677212.post-7056824811779408457</id><published>2009-02-08T15:21:00.013-05:00</published><updated>2009-02-15T00:44:30.160-05:00</updated><title type='text'></title><content type='html'>&lt;span style="font-size:180%;"&gt;The Zen of Jess 2009:  Part I&lt;/span&gt;&lt;br /&gt;by Jason Morris&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-weight: bold;"&gt;Jess and the Art of (Safe) Rule-Based Computing&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I’ve noted that new Jess users are highly susceptible to the viral coding malady, &lt;span style="font-style: italic;"&gt;scribo precoxium&lt;/span&gt; (SP), roughly translated from Latin as “to write prematurely”.  Most poor souls who contract &lt;span style="font-style: italic;"&gt;scribo precoxium&lt;/span&gt; come from relatively weak Java backgrounds.  Their bookshelves are devoid of the names Giarratano, Riley, Russell, Norvig, and Jackson, though the sharing of books with the phrases “head-first” or “in a nutshell” seems to be higher among the population of &lt;span style="font-style: italic;"&gt;scribo precoxium&lt;/span&gt; sufferers.  The typical progression finds casual coders hanging out in unmoderated forums leading to &lt;span style="font-style: italic;"&gt;libri indifferens&lt;/span&gt;, or an indifference to reading reference material.  Longer exposure gives way to outright Documentational Disaffective Disorder.  In no time, victims are attempting complicated Jess applications without first doing any homework, and once they start writing a little code, the urge to continue cannot be controlled.  Soon, they are left exasperated, due dates looming, with piles of uncompilable source.  First responders on the scene often report victims face down in puddle of Mountain Dew, comatose from trying to ease their pain by mainlining a snowball of Jess and Drools.&lt;br /&gt;&lt;br /&gt;Professionals are less susceptible than academics to SP, though even the most seasoned veteran of many product cycles has been known to contract it.  As trained help providers, we on the Jess list server are keen to spot the warning signs.  Typical symptoms of SP include severe external pleading such as, “&lt;span style="font-style: italic;"&gt;Help me please!&lt;/span&gt;” and “&lt;span style="font-style: italic;"&gt;I can’t get this to run!&lt;/span&gt;”.  Often, there is an additional appeal for assistance by a certain date such as, “&lt;span style="font-style: italic;"&gt;I need to make this work by tomorrow!!&lt;/span&gt;” or something similar.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_GpzkbrexfHA/SZerUSPlJQI/AAAAAAAAABw/hP5COEeawb8/s1600-h/RTFD_tablets.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; float: right; cursor: pointer; width: 174px; height: 320px;" src="http://4.bp.blogspot.com/_GpzkbrexfHA/SZerUSPlJQI/AAAAAAAAABw/hP5COEeawb8/s320/RTFD_tablets.jpg" alt="" id="BLOGGER_PHOTO_ID_5302895451234968834" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;What can be done?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Fortunately, there is a time-tested treatment for combating &lt;span style="font-style: italic;"&gt;scribo precoxium&lt;/span&gt;: RTFD.  When given intra-occularly, RTFD has been proven in the vast majority of cases to eliminate the symptoms of SP overnight.  Small doses of RTFD, taken daily, can prevent the reoccurrence of &lt;span style="font-style: italic;"&gt;scribo precoxium&lt;/span&gt;.  Left untreated, SP can metastize into full-blown &lt;span style="font-style: italic;"&gt;molestus neophytus&lt;/span&gt; which can impair your hearing, judgment, and ability to take sound programming advice of any kind.  In the most serious cases, patients are have been known to develop an &lt;span style="font-style: italic;"&gt;owen-oma&lt;/span&gt;, an ulcerated rip midway between their eyes and halfway up their forehead.&lt;br /&gt;&lt;br /&gt;So, don’t hesitate to write Dr. Friedman-Hill if you need your RTFD prescription refilled.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A New Beginning&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;All kidding aside, in the five years since I first wrote &lt;span style="font-style: italic;"&gt;The Zen of Jess&lt;/span&gt;, Jess has acquired a significant body of questions and answers on the Jess email list.  Most of these answers come from Dr. Friedman-Hill himself, and though I originally opined that he must be frustrated in having to answer questions that he has taken great pains to answer elsewhere, one would never know it for the effort that he makes ensuring that every question, however “noobious”, is answered.  It has occurred to me that despite all the warnings, admonitions, and evidence to the contrary, there are those for whom the cart must come before the horse.  So, in keeping with our great Madame Speaker’s penchant for prevention of communicable diseases such as &lt;span style="font-style: italic;"&gt;scribo precoxium&lt;/span&gt;, I shall advocate a policy of Prophylactic Programming.&lt;br /&gt;&lt;br /&gt;Lest you contract SP, keep in mind that using Jess is not so simple as including another JAR in your application. Jess is in many ways a meta-tool, that is a tool for building tools – in my case rule-based expert systems.  For many new Jess users, declarative programming will be a completely alien paradigm that warrants a careful and thoughtful study &lt;span style="font-style: italic;"&gt;before &lt;/span&gt;attempting to write serious code.&lt;br /&gt;&lt;br /&gt;We'll delve into what that entails in Part II. - JM&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-7056824811779408457?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/7056824811779408457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=7056824811779408457' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/7056824811779408457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/7056824811779408457'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2009/02/zen-of-jess-2009-part-i-by-jason-morris.html' title=''/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_GpzkbrexfHA/SZerUSPlJQI/AAAAAAAAABw/hP5COEeawb8/s72-c/RTFD_tablets.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35677212.post-6482932129300324552</id><published>2009-01-28T15:13:00.067-05:00</published><updated>2009-01-29T17:15:02.988-05:00</updated><title type='text'>Introducing the SINFERS Project</title><content type='html'>&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;br /&gt;Hi All,&lt;br /&gt;After a nearly three year hiatus and at the bequest of James Owen, I have decided to reactivate my blog.  To motivate myself, I'll start a thread about my on-going work with the University of Sydney, Australia.  Since May of 2006, I've been working with a super chap by the name of Grant Tranter, a PhD candidate in the Department of Soil Science, Faculty of Agriculture, Food and Natural Resources at UniS.  Together, we've been creating an expert system called SINFERS that uses Jess to infer unknown soil properties from a set of known input data.&lt;br /&gt;&lt;br /&gt;The underlying theory of SINFERS rests on the concept of a &lt;a href="http://en.wikipedia.org/wiki/Pedotransfer_function"&gt;pedotransfer function&lt;/a&gt; (PTF) - as predictive functions of certain soil properties from other more available, easily, routinely, or cheaply measured properties [&lt;a href="http://www.blogger.com/post-edit.g?blogID=35677212&amp;amp;postID=6482932129300324552#footnote_1"&gt;1&lt;/a&gt;].  SINFERS ultimately will have 300-500 such PTFs at its disposal for computing soil properties.  Listing 1 is a typical example.&lt;br /&gt;&lt;br /&gt;&lt;pre  style="border: thin solid rgb(0, 0, 0); padding: 3px; background-color: rgb(240, 248, 255);font-family:Courier New;"&gt;34.0023360256908 - 0.171438746911598 * P10_NR_Z - 0.333101650254256 * P10_NR_S&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;Listing 1.  A PTF for computing 15 BAR Moisture g/g by gravimetric pressure plate&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The above PTF has to do with soil water content, which can be measured to determined other characteristics under certain conditions (i.e., wilting point and field capacity). Such an examination yields the moisture released, and such tests are conducted under specific suction pressures (15 BAR and 0.3 BAR).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;How SINFERS Works&lt;/span&gt;&lt;br /&gt;A user inputs a set of soil property data that we, as a convention, refer to as a &lt;span style="font-style: italic;"&gt;batch&lt;/span&gt;.  SINFERS has a &lt;span style="font-style: italic;"&gt;knowledgebase &lt;/span&gt;that relates the arguments of each serialized PTF in its PTF database to the entered soil properties.   If SINFERS recognizes a subset of those soil properties as matching the arguments to a particular PTF, that PTF is de-serialized, instantiated as a Java object, and is made available to SINFERS.  The instantiated PTF object has methods that allow it to compute a value for its dependent variable as well as an estimate of the error.&lt;br /&gt;&lt;br /&gt;When a PTF calculates a new soil property, that property is placed in working memory along with the initial set.  The addition of such new properties generates new subsets that match the argument lists of other PTFs and the process repeats until the knowledgebase is exhausted and all possible soil properties have been inferred from the initial set.  A typical PTF propose rule is given in Listing 2.&lt;br /&gt;&lt;pre  style="border: thin solid rgb(0, 0, 0); padding: 3px; background-color: rgb(240, 248, 255);font-family:Courier New;"&gt;(&lt;span style="font-weight: bold;"&gt;defrule &lt;/span&gt;propose::ptf_P3A1_1&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"Computes the soil bulk density - (g/cm^3)"&lt;/span&gt;&lt;br /&gt;(soil-property (batchId ?id)(labCode depth)(value ?depth)(error ?edepth)&lt;br /&gt;(status normal|initial)(ptf ?ptf1))&lt;br /&gt;(soil-property (batchId ?id)(labCode _6A1)(value ?_6A1)(error ?e_6A1)&lt;br /&gt;(status normal|initial)(ptf ?ptf2))&lt;br /&gt;(soil-property (batchId ?id)(labCode P10_NR_S)(value ?P10_NR_S)(error ?eP10_NR_S)&lt;br /&gt;(status normal|initial)(ptf ?ptf3))&lt;br /&gt;=&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;; Propose a candidate value and error for this PTF.&lt;/span&gt;&lt;br /&gt;(ptf-propose-candidate P3A1_PTF_1 P3A1 "1.36892296397839 - 0.138035067345618 * depth&lt;br /&gt;- 0.321710483557874 * log10(_6A1) + 0.00198950541325674 * P10_NR_S +&lt;br /&gt;( P10_NR_S - 48.8224031007752) * (P10_NR_S - 48.8224031007752) * -0.0000884352051558744"&lt;br /&gt;(list depth _6A1 P10_NR_S)(list ?depth ?_6A1 ?P10_NR_S)&lt;br /&gt;(list ?edepth ?e_6A1 ?eP10_NR_S)))&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;br /&gt;Listing 2.  A PTF rule for computing soil bulk density using the given regression expression.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Lest it appear that the process of selecting PTFs is straight forward, let me point out that not only do the rules have to select which PTFs to apply, but they also have to allow the computed value and uncertainty of any soil property to be updated with a &lt;span style="font-style: italic;"&gt;less uncertain&lt;/span&gt; one provided that:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The update does not cause a circular reference.&lt;/li&gt;&lt;li&gt;The update does not overwrite an initial input property.&lt;/li&gt;&lt;/ul&gt;SINFERS uses a modified &lt;span style="font-style: italic;"&gt;propose and revise&lt;/span&gt; problem-solving method, implemented by three Jess modules.  The &lt;span style="font-style: italic;"&gt;propose module&lt;/span&gt; contains rules that allow each activated PTF rule to go ahead and compute its value and uncertainty, asserting these as &lt;span style="font-style: italic;"&gt;candidates &lt;/span&gt;for consideration by the select module.  A third module, the &lt;span style="font-style: italic;"&gt;revise module&lt;/span&gt; handles special cases.  For example, if a PTF rule is activated, and the very property it is set to replace was used to compute one of its arguments, a circular reference forms and we abort the computation.&lt;br /&gt;&lt;br /&gt;An example of a select rule is given in Listing 3.&lt;br /&gt;&lt;br /&gt;&lt;pre face="Courier New" style="border: thin solid rgb(0, 0, 0); padding: 3px; background-color: rgb(240, 248, 255);"&gt;(&lt;span style="font-weight: bold;"&gt;defrule &lt;/span&gt;select::choose-best-soil-property-P3A1&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;"Selects best candidate providing most certain P3A1 and removes next best loser from WM"&lt;/span&gt;&lt;br /&gt;(declare (auto-focus TRUE))&lt;br /&gt;?sp1 &lt;-(soil-property (batchId ?id)(id ?id1)(error ?e1)(status candidate) &lt;br /&gt;(labCode P3A1) (value ?v1)(ptf ?ptf1))    &lt;br /&gt;?sp2 &lt;-(soil-property (batchId ?id)(id ?id2&amp;amp;~?id1) (error ?e2&amp;amp;:(&lt; ?e2 ?e1)) &lt;br /&gt;(status candidate) (labCode P3A1) (value ?v2)(ptf ?ptf2))    &lt;br /&gt;&lt;br /&gt;=&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 153, 0);"&gt;  ; Remove loser&lt;/span&gt;&lt;br /&gt;(retract ?sp1)&lt;br /&gt;(printout t "ptf-" ?ptf2 " has replaced ptf-" ?ptf1 " for&lt;br /&gt;providing the most certain  P3A1 value = " ?v2 ", error = " ?e2 crlf))&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;Listing 3.  A selection rule for choosing the best bulk density computation.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I will save a detailed explanation of the inferencing logic for a later blog.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Getting Automated&lt;/span&gt;&lt;br /&gt;I'll start this thread by talking about how we automated some of the build processes concerning the SINFERS knowledgebase.  One of the early decisions was to integrate using Jython as an auxiliary scripting language for SINFERS.  Jython provides a handy command line interpreter class that can be plugged into any Java application.  With Jython, there is no need to use a tool like ANTLR to write your own scripting language.  In fact, we could have used Jess as the internal scripting language for SINFERS (and may still for some parts of it) since Jess (the language) provides many of the same features.  The cool thing is that we can drive Jess from Jython as well, so we get the best of both worlds.&lt;br /&gt;&lt;br /&gt;When complex rules can be developed by applying a set of parameters to a template, it makes sense to automate the creation of that rule set.  Rather than add potentially brittle classes to the SINEFRS API, we decided to write simple Jython scripts to generate our rules.&lt;br /&gt;&lt;br /&gt;The Jython function that generates the proposal rules is given in Listing 4 below.&lt;br /&gt;&lt;br /&gt;&lt;pre style="border: thin solid rgb(0, 0, 0); padding: 3px; background-color: rgb(240, 248, 255); font-family: Courier New;"&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;def &lt;/span&gt;&lt;span style="font-size:85%;"&gt;makeRules(databasePath):&lt;br /&gt;sys = System&lt;br /&gt;rules = StringBuffer()&lt;br /&gt;rules.append('(defmodule propose)\n\n')&lt;br /&gt;&lt;br /&gt;xmlFileObj = getFileFromPath(databasePath)&lt;br /&gt;dom = loadXMLDocument(xmlFileObj)&lt;br /&gt;dependentVars = ArrayList()&lt;br /&gt;&lt;br /&gt;root = dom.getRootElement();&lt;br /&gt;&lt;br /&gt;ptfsCol = root.getChild('ptfs')&lt;br /&gt;ptfs = ptfsCol.getChildren('ptf')&lt;br /&gt;&lt;br /&gt;i = 1&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0); font-weight: bold;font-size:85%;" &gt;for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;ptf &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;in &lt;/span&gt;&lt;span style="font-size:85%;"&gt;ptfs:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-size:85%;" &gt;# Set var count&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;n = 1&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-size:85%;" &gt;# Extract all the body elements&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;ptfIdElement = ptf.getChild('id')&lt;br /&gt;ptfLabCodeElement = ptf.getChild('labCode')&lt;br /&gt;ptfNameElement = ptf.getChild('ptfName')&lt;br /&gt;ptfFunctionTypeElement = ptf.getChild('functionType')&lt;br /&gt;ptfLinsCorrelationCoefficientElement = ptf.getChild('linsCorrelationCoefficient')&lt;br /&gt;ptfRmsErrorElement = ptf.getChild('rmsError')&lt;br /&gt;ptfDependentTransformElement = ptf.getChild('dependentTransformation')&lt;br /&gt;ptfCovarianceMatrixElement = ptf.getChild('covarianceMatrix')&lt;br /&gt;ptfClusterCountElement = ptf.getChild('clusterCount')&lt;br /&gt;ptfTrainingSampleCountElement = ptf.getChild('trainingSampleCount')&lt;br /&gt;ptfAlphaElement = ptf.getChild('alpha')&lt;br /&gt;ptfFuzzyExponentElement = ptf.getChild('fuzzyExponent')&lt;br /&gt;ptfExpressionElement = ptf.getChild('expression')&lt;br /&gt;ptfCreationDateElement = ptf.getChild('creationDate')&lt;br /&gt;ptfCountryCodeElement = ptf.getChild('countryCode')&lt;br /&gt;ptfIndependentVariablesCol = ptf.getChild('independentVariables')&lt;br /&gt;ptfIndependentVariables = ptfIndependentVariablesCol&lt;br /&gt;.getChildren('independentVariable')&lt;br /&gt;ptfTrainingClustersCol = ptf.getChild('trainingClusters')&lt;br /&gt;ptfTrainingClusters = ptfTrainingClustersCol.getChildren('trainingCluster')&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-size:85%;" &gt;# Extract the field values&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;ptfId = ptfIdElement.getText()&lt;br /&gt;ptfLabCode = ptfLabCodeElement.getText()&lt;br /&gt;ptfName = ptfNameElement.getText()&lt;br /&gt;ptfFunctionType = ptfFunctionTypeElement.getText()&lt;br /&gt;ptfLinsCorrelationCoefficient = ptfLinsCorrelationCoefficientElement.getText()&lt;br /&gt;ptfRmsError = ptfRmsErrorElement.getText()&lt;br /&gt;ptfDependentTransform = ptfDependentTransformElement.getText()&lt;br /&gt;ptfCovarianceMatrix = ptfCovarianceMatrixElement.getText()&lt;br /&gt;ptfClusterCount = ptfClusterCountElement.getText()&lt;br /&gt;ptfTrainingSampleCount = ptfTrainingSampleCountElement.getText()&lt;br /&gt;ptfAlpha = ptfAlphaElement.getText()&lt;br /&gt;ptfFuzzyExponent = ptfFuzzyExponentElement.getText()&lt;br /&gt;ptfExpression = ptfExpressionElement.getText()&lt;br /&gt;ptfCreationDate = ptfCreationDateElement.getText()&lt;br /&gt;ptfCountryCode = ptfCountryCodeElement.getText()&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-size:85%;" &gt;# Store the dependent variable lab codes for later&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;dependentVars.add(ptfLabCode)&lt;br /&gt;&lt;br /&gt;rules.append('(defrule propose::ptf_' + ptfLabCode + '_' + ptfId + '\n')&lt;br /&gt;rules.append('\"Insert ptf purpose here\"\n')&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-size:85%;" &gt;# Store the PTF arguments for later&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;args = ArrayList()&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;variable &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;in &lt;/span&gt;&lt;span style="font-size:85%;"&gt;ptfIndependentVariables:&lt;br /&gt; varLabCodeElement = variable.getChild('labCode')&lt;br /&gt; varLabCode = varLabCodeElement.getText()&lt;br /&gt; args.add(varLabCode)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-size:85%;" &gt;# Create a conditional element for each argument in the PTF&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;variable &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;in &lt;/span&gt;&lt;span style="font-size:85%;"&gt;ptfIndependentVariables:&lt;br /&gt; varLabCodeElement = variable.getChild('labCode')&lt;br /&gt; varLabCode = varLabCodeElement.getText()&lt;br /&gt; rules.append('(soil-property (batchId ?id)(labCode ' +&lt;br /&gt;              varLabCode + ')(value ?' +&lt;br /&gt;              varLabCode + ')(error ?e' +&lt;br /&gt;              varLabCode + ') (status normal|initial)(ptf ?ptf' +&lt;br /&gt;              str(n) + '))\n')&lt;br /&gt; n = n + 1&lt;br /&gt;rules.append('=&gt;\n')&lt;br /&gt;rules.append('; ?ptfName ?labCode ?expression ?arg-syms ?arg-vals ?arg-errs\n')&lt;br /&gt;rules.append('(ptf-propose-candidate ' + ptfName + ' ' +&lt;br /&gt;          ptfLabCode + ' \"' + ptfExpression + '\" ')&lt;br /&gt;rules.append('(list')&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;arg &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;in &lt;/span&gt;&lt;span style="font-size:85%;"&gt;args:&lt;br /&gt; rules.append(' ' + arg)&lt;br /&gt;rules.append(') ')&lt;br /&gt;rules.append('(list')&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;arg &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;in &lt;/span&gt;&lt;span style="font-size:85%;"&gt;args:&lt;br /&gt; rules.append(' ?' + arg)&lt;br /&gt;rules.append(') ')&lt;br /&gt;rules.append('(list')&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;arg &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;in &lt;/span&gt;&lt;span style="font-size:85%;"&gt;args:&lt;br /&gt; rules.append(' ?e' + arg)&lt;br /&gt;rules.append(')))\n\n')&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 153, 0);font-size:85%;" &gt;# Build the selection rules&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;br /&gt;rules.append('(defmodule select)\n\n')&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;for &lt;/span&gt;&lt;span style="font-size:85%;"&gt;var &lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;in &lt;/span&gt;&lt;span style="font-size:85%;"&gt;dependentVars:&lt;br /&gt;rules.append('(defrule select::choose-best-soil-property-' + var + '\n')&lt;br /&gt;rules.append('\"Selects the best candidate for soil property ' +&lt;br /&gt;          var + ' and removes the next best loser from WM\"\n')&lt;br /&gt;rules.append('(declare (auto-focus TRUE))\n')&lt;br /&gt;rules.append('?sp1 &lt;-(soil-property (batchId ?id)(id ?id1)(error ?e1)' +           &lt;br /&gt; '(status candidate) (labCode ' + var + ') (value ?v1) (ptf ?ptf1))\n')       &lt;br /&gt;rules.append('?sp2 &lt;-(soil-property (batchId ?id)(id ?id2&amp;amp;~?id1)' +            &lt;br /&gt; '(error ?e2&amp;amp;:(&lt; ?e2 ?e1)) (status candidate) (labCode ' +  var + ')' +   &lt;br /&gt; '(value ?v2) (ptf ?ptf2))\n') &lt;br /&gt;rules.append('=&gt;')&lt;br /&gt;rules.append('; Remove loser\n')&lt;br /&gt;rules.append('(retract ?sp1)\n')&lt;br /&gt;rules.append('(printout t "ptf-" ?ptf2 " has defeated ptf-" ?ptf1 " ' +&lt;br /&gt;' for soil property ' + var + ' value = " ?v2 ", error = " ?e2 crlf))\n\n')&lt;br /&gt;&lt;br /&gt;sys.out.println('Rule file written OK.  \nOUTPUT: ' + ruleOutputFile)&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;return &lt;/span&gt;&lt;span style="font-size:85%;"&gt;rules.toString()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;Listing 4.  A Jython function for generating SINFERS PTF rules.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;In the next installment, I'll talk more about the inferencing considerations and how we arrived at the logic.&lt;br /&gt;&lt;br /&gt;-JM&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;hr /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;a name="footnote_1"&gt;[1] See http://en.wikipedia.org/wiki/Pedotransfer_function&lt;/a&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-6482932129300324552?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/6482932129300324552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=6482932129300324552' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/6482932129300324552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/6482932129300324552'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2009/01/introducing-sinfers-project.html' title='Introducing the SINFERS Project'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35677212.post-116090581369890860</id><published>2006-10-15T03:48:00.000-05:00</published><updated>2006-11-20T13:00:27.893-05:00</updated><title type='text'>Open Thread:  Fuzzy Backward Chaining Rules</title><content type='html'>Jess programmers know that Jess is, by design, a forward-chaining rule engine that makes deductive inferences. However, it is also quite capable of making inductive inferences by backward chaining.   Additionally, I think that it's safe to say that most Jess programmers primarily work with bivalent or "crisp" logic wherein all expressions can be evaluated as TRUE or FALSE and variables have a definite value.&lt;br /&gt;&lt;br /&gt;Some years ago, &lt;a href="http://iit-iti.nrc-cnrc.gc.ca/careers-carrieres/bob_e.html"&gt;Bob Orchard&lt;/a&gt; created the FuzzyJ toolkit featuring &lt;a href="http://www.iit.nrc.ca/IR_public/fuzzy/fuzzyJToolkit2.html"&gt;FuzzyJess&lt;/a&gt;, which added fuzzy logic capabilities to Jess proper. Fuzzy logic allows one to reason with imprecise quantities where boundaries between TRUE and FALSE are blurred and variables can have "membership" in more than one set at a time. Real-world applications include substitutions for traditional feedback-control systems (heavy equipment stability, camera and video autofocus, video "jiggle" correction) and numerous process control examples. An example of a forward-chaining, fuzzy logic control applications can be found in Part 5, Chapter 14 of Ernest Friedman-Hill's &lt;em&gt;Jess In Action &lt;/em&gt;(Manning, 2003).&lt;br /&gt;&lt;br /&gt;Of the Top Ten Uses for rule-based expert systems commonly mentioned in the literature (interpretation, prediction, diagnosis, design, planning, monitoring, debugging, repair, and instruction, it is the last -- control -- which indeed seems to favor fuzzy, forward chaining applications.&lt;br /&gt;&lt;br /&gt;Now, I have coded a good number of crisp, forward chaining systems, and I have experimented with fuzzy forward-chaining systems. I have also coded crisp, backward-chaining apps. However, I have yet to see &lt;em&gt;any&lt;/em&gt; example of a &lt;em&gt;fuzzy&lt;/em&gt;, &lt;em&gt;backward-chaining&lt;/em&gt; expert system.&lt;br /&gt;&lt;br /&gt;In fact, in my quick lit search, I was only able to find two papers in the last twelve years:&lt;br /&gt;&lt;br /&gt;[1] Amould, Thierry , Tano, Shun'ichi; "Definition and Formulation of Backward-reasoning with Fuzzy If... Then... Rules", Fuzzy Systems, IEEE World Congress on Computational Intelligence, Proceedings of the Third IEEE Conference on, 864-869 vol.2, June 1994.&lt;br /&gt;&lt;br /&gt;[2] Kashiwagi, D., Moor, W.; APPLICATION OF BACKWARD CHAINING, "FUZZY LOGIC," AND THE MANAGEMENT OF INFORMATION TO PROCUREMENT OF FACILITY SYSTEMS/SERVICES, Proceedings of the 17th International Conference on Computers and Industrial Engineering, pp. 399 - 403, 1995.&lt;br /&gt;&lt;br /&gt;I have already identified where backward chaining would be useful in my research, and I suspect that fuzzy rules might perform better than crisp ones for my intended application. I was wondering if anyone out there has significant experience in coding fuzzy, backward-chaining expert systems; and, if so, would you please recommend some current literature?&lt;br /&gt;&lt;br /&gt;Any thoughts or anecdotes about the topic are welcome!&lt;br /&gt;Cheers,&lt;br /&gt;-JM&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-116090581369890860?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/116090581369890860/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=116090581369890860' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/116090581369890860'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/116090581369890860'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2006/10/open-thread-fuzzy-backward-chaining.html' title='Open Thread:  Fuzzy Backward Chaining Rules'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35677212.post-116045873956340960</id><published>2006-10-09T23:47:00.000-05:00</published><updated>2006-10-10T01:53:42.253-05:00</updated><title type='text'>Blogspeed</title><content type='html'>&lt;span style="font-family:trebuchet ms;"&gt;In my long ago undergrad days at &lt;/span&gt;&lt;a href="http://www.msu.edu/"&gt;&lt;span style="font-family:trebuchet ms;"&gt;Michigan State&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:trebuchet ms;"&gt;, we had a local radio station, &lt;/span&gt;&lt;a href="http://www.q106fm.com/"&gt;&lt;span style="font-family:trebuchet ms;"&gt;Q-106&lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:trebuchet ms;"&gt;, that was notorious for its riske' adverts and great tunes during a period when "alternative rock" was emerging and "grunge" was in its infancy in Seattle. In one 15 second spot, the Announcer cheekily quipped in his best lounge-lizard voice:&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Hey... it's not the size&lt;/em&gt; [of your antenna] &lt;em&gt;... it's the frequency&lt;/em&gt; [of your signal] &lt;em&gt;Q-106&lt;/em&gt;!&lt;br /&gt;&lt;br /&gt;Fast-forward twenty years as I sit thinking about &lt;em&gt;how often I should blog&lt;/em&gt; and &lt;em&gt;is less really more&lt;/em&gt;. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:trebuchet ms;"&gt;For the political bloggers and other professional pundits, it is not uncommon to post multiple times during the day, especially on busy news days. For the "tweens" on &lt;/span&gt;&lt;a href="http://www.myspace.com/"&gt;&lt;span style="font-family:trebuchet ms;"&gt;myspace &lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:trebuchet ms;"&gt;and such, once a day might suffice. Professional columnists who need to fact-check, to compile references, and to build convincing arguments need to take a bit longer -- perhaps more like a weekly or bi-weekly column. That said, being a blogging newbie, there did seem to me to be an inordinate pressure to crank out posts. The more that I thought about it, the more it seemed that posting for posting sake would just lead to lots of posts like... well... like this one!&lt;br /&gt;&lt;br /&gt;Then I read this little &lt;/span&gt;&lt;a href="http://www.mpdailyfix.com/2006/06/w_why_blog_post_frequency_does.html"&gt;&lt;span style="font-family:trebuchet ms;"&gt;blog &lt;/span&gt;&lt;/a&gt;&lt;span style="font-family:trebuchet ms;"&gt;by Eric Kintz at Hewlett-Packard. It made a lot of practical sense, and (ribbing Mr. Kintz) I would &lt;em&gt;so&lt;/em&gt; not want Jess to be "Web 1.0", too.  I concluded that ..."&lt;em&gt;it's the frequency!&lt;/em&gt;" just might not hold anymore.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;/span&gt;&lt;p&gt;&lt;span style="font-family:trebuchet ms;"&gt;This then is my initial goal: &lt;/span&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt;At the very least I will aim to post one in-depth blog per week&lt;/strong&gt;, often contributed by a Guest Blogger TBA. The topic will always be strongly Jess-related and more like an essay or article of hopefully useful information. More formal and less prosy in style. Quality over quantity.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt;I will abstain from consuming bandwidth daily&lt;/strong&gt; unless a useful subtopic materializes. Expect it to be at least tangentially related to Jess (i.e., my research, other folks research, my consulting, business rules, rule-engines, or rule-based expert systems, etc.). Here, I'll relax a bit, sip a coffee, and chat with you about the field.&lt;br /&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt;I will post any important breaking news&lt;/strong&gt; as soon as I know about it.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-family:trebuchet ms;"&gt;&lt;strong&gt;Epilogue &lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;Extrapolating my opening metaphor, a friend innocently suggested that I only post "&lt;em&gt;at noon&lt;/em&gt;" so as to &lt;em&gt;"...quickly disseminate&lt;/em&gt;" my information and get on with my day...&lt;br /&gt;&lt;br /&gt;Oh dear!! I shall henceforth check all loaded metaphors at the door. -JM &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-116045873956340960?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/116045873956340960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=116045873956340960' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/116045873956340960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/116045873956340960'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2006/10/blogspeed.html' title='Blogspeed'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-35677212.post-116027866682563212</id><published>2006-10-07T22:28:00.000-05:00</published><updated>2006-10-09T11:57:53.803-05:00</updated><title type='text'>Let The Zen Begin</title><content type='html'>I am starting a new blog that has a main focus on &lt;a href="http://www.jessrules.com"&gt;Jess&lt;/a&gt;, the Java Expert Systems Shell, as it relates to my Ph.D. research into Intelligent Tutoring Systems at &lt;a href="http://www.wpi.edu"&gt;Worcester Polytechnic Institute &lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;My hope is that by writing down my thoughts, ideas, discoveries, false starts, and outright blunders that I'll eventually have some mad Jess skillz.&lt;br /&gt;&lt;br /&gt;Perhaps these insights will help you in your academics or professional work, too.&lt;br /&gt;&lt;br /&gt;If so, please drop me an email!&lt;br /&gt;&lt;br /&gt;Cheers,&lt;br /&gt;-JM&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/35677212-116027866682563212?l=zen-of-jess.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://zen-of-jess.blogspot.com/feeds/116027866682563212/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=35677212&amp;postID=116027866682563212' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/116027866682563212'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/35677212/posts/default/116027866682563212'/><link rel='alternate' type='text/html' href='http://zen-of-jess.blogspot.com/2006/10/let-zen-begin.html' title='Let The Zen Begin'/><author><name>jcmorris</name><uri>http://www.blogger.com/profile/04373051963131928238</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='19' height='32' src='http://2.bp.blogspot.com/_GpzkbrexfHA/SWaHcGOFeTI/AAAAAAAAAAM/XrN0RywfYlE/S220/head_me_color.gif'/></author><thr:total>1</thr:total></entry></feed>
