Skip to main content

If you don't have an IBM ID and password, register here.

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

Adding rules to applications

Use the ABLE Rule Language to write simple business rules or more complex inferencing rules

Jeff Pilgrim, Advisory Software Engineer, IBM STG Custom Technology Center
Jeff Pilgrim is an Advisory Software Engineer assigned to the ABLE research team at IBM eServer Software Services in Rochester, Minnesota. His previous development experience includes work on Intelligent Miner for Data, Neural Network Utility, wide area wireless computing, and systems management. He was a developer and architect for several system configurators, as well as for numerous internal industrial engineering applications. Jeff originally joined IBM at its Federal Systems Division in Owego, NY, where he was responsible for forecasting workload for defense contracts. He holds a Master of Science degree in Industrial Engineering and Operations Research from the Pennsylvania State University.
Joe Bigus, Senior Technical Staff Member, IBM T. J. Watson Research Center
Joe Bigus is a Senior Technical Staff Member at the IBM T. J. Watson Research Center, where he is the project leader on the ABLE research project. He is a member of the IBM Academy of Technology and is an IBM Master Inventor, with over 20 U.S. patents. Dr. Bigus was an architect of the IBM Neural Network Utility and Intelligent Miner for Data products. He received his M.S. and Ph.D. degrees in Computer Science from Lehigh University and a B.S. in Computer Science from Villanova University. He has written two books: Data Mining with Neural Networks (McGraw-Hill) and Constructing Intelligent Agents with Java (Wiley). Dr. Bigus's current research interests include learning algorithms and intelligent agents, as well as multiagent teams and their applications to adaptive system modeling and control, data mining, and decision support.
Don Schlosnagle, Advisory Software Engineer, IBM STG Custom Technology Center
Don Schlosnagle is an Advisory Software Engineer at IBM eServer Software Services in Rochester, Minnesota. He studied computational linguistics and expert systems at SRI and wrote, in Common Lisp, a PC-based natural language DB2 query program that was successfully marketed by IBM as a PRPQ. Mr. Schlosnagle has since worked on the Neural Network Utility and on Intelligent Miner for Data, where he contributed the fuzzy logic inference system for evaluating proposed neural network architectures. A greatly enhanced version of the fuzzy system found its way into ABLE. Mr. Schlosnagle's current interest is in combining neural networks with fuzzy logic.

Any of the authors can be contacted by e-mail through ableinfo@us.ibm.com.

Summary:  Write and run simple business rules or complex inferencing rules using the Agent Building and Learning Environment (ABLE) and its ABLE Rule Language (ARL). Example rulesets show ARL's syntax and capabilities, how to work with Java™ objects from ARL, how to write and debug rules in Eclipse, how to run rulesets from Java applications, demonstrate procedural and inferencing rule engines, and see the benefits of using rules written for inferencing rule engines.

Date:  15 Feb 2005
Level:  Intermediate

Comments:  

Introducing ABLE rules

The Agent Building and Learning Environment (ABLE) is a Java-based framework, component library, and productivity toolkit for building intelligent agents that can use machine learning and reasoning. ABLE is designed to be used by applications involved in autonomic computing, business rules, data mining, diagnostics, forecasting, planning, policy management, retail, and resource balancing. ABLE's reasoning component includes a rule-based programming language known as ABLE Rule Language (ARL). This article introduces you to ARL and shows you how to use the Eclipse plug-in rule editor provided with the alphaWorks® download.

Rules separate business policies from program logic. Applications typically obtain data externally from logic, and are designed to allow change as needed. Logic separated from programs and expressed as rules can be readily authored and rapidly altered, just as externalized data can be. Using rules allows non-programmers like analysts and managers to make changes directly given tools designed for their use.

With ARL you can express your business logic outside of your program logic using simple If-Then rules or more complex inferencing rules. To process those rules, ABLE provides a set of rule processing engines ranging from simple procedural scripting, to forward and backward chaining, to artificial intelligence inferencing techniques. You can mix any of those processing engines within a set of rules, and as your application's requirements grow, your ruleset can evolve with them. The ARL language includes expressions, templates, and fuzzy logic; all features that can be used to make rules more readable and more readily changed.

ARL is intended for a technical audience, but not necessarily programmers. Indeed, programmers often have difficulty expressing logic in rules because the process flow can be considerably different. ARL provides tight integration with Java objects, and the tooling provided with ABLE is based on the Eclipse platform. Java programmers will have a head start, but, you really don't need to know Java or understand artificial intelligence to use ABLE's ARL component.

For a list of rule engines and how to install the example rulesets, see Features and Facets of ABLE. From here on, you can follow the remainder of the article in Eclipse as a tutorial if you want. Eclipse Version 2.1 is the target platform for ABLE Version 2.2, and the ABLE plug-in can be obtained from alphaWorks at http://www.alphaworks.ibm.com/tech/able using these installation instructions. Unzip this collection of rulesets into an Eclipse Java project, such as the example ruleset project.


Hello World in the ABLE Rule Language

Listing 1 shows the ABLE Rule Language equivalent of Hello World.


Listing 1. The HelloWorld ruleset

/**  An ABLE RuleSet...  */
ruleset RuleSet_0 {
  variables {
    String helloWorld = new String("Able rules!"); // One variable minimum
  } 
  inputs{};
  outputs{};
  void process() using Script {
    Rule0: println(helloWorld); // One rule minimum 
  }
}


Running a ruleset in Eclipse

From a new or existing Eclipse Java project in the Java perspective, click New to create a ruleset. Right-click and select New > Other > Able > Ruleset. Create this basic ruleset from the wizard, and you'll see a pre-populated HelloWorld ruleset as in the BasicRuleSet1 example.


Figure 1. A ruleset launch configuration in Eclipse
A ruleset launch configuration in Eclipse

When you press Run, you should see the text “Able rules!" in the console view. Creating Run or Debug configurations using Run as > ABLE ruleset is not provided with the ABLE Version 2.2 plug-in support.

Formatting conventions used in this article:

  • Italics are used to show ruleset names.
  • Code is used for ruleblock names and variable names.

Using Java in a ruleset

Let's compare using Java to ARL. Like a Java class, saving a ruleset in Eclipse causes it to be parsed and an Outline view created. From the navigator and outline views, you can see that there are other comparisons that can be readily made between ARL rulesets and Java classes:


Table 1. Comparing ARL to Java classes
In ARLIn Java
Source file extension.arl (.arml for XML).java
File contentrulesetclass(es)
Unit of workruleblockmethod
Control structuredefined by rule engineprocedural
Linerulecode
Line labelrequiredoptional
Line terminatorsemi-colon (;)semi-colon (;)
Comment//, /* */, /** *///, /* */, /** */
ImportJava classesJava classes
ExtendrulesetsJava classes
Castingimplicitexplicit

We'll use the ruleset JavaRuleSet1 to discuss a few differences between ARL and Java technology.


Listing 2. Using Java objects in a ruleset
ruleset JavaRuleSet1 {
  import java.util.Vector;
  variables {
  	 Integer count = 1;
     static Vector list = new Vector();
  } 
  void process() using Script {
  	p1: list.add("Item "+count);
  	p2: println("Count = "+count + "List.size()="+list.size());
  	p3: count = count + 1;
  }
}

Remember running the HelloWorld ruleset shown in Listing 1? A Java class would need a main method to do that. In ARL, the main method is a ruleblock named process. Java methods run with a procedural, top-down control structure. The control structure used to process an ARL ruleblock varies, with the default being Script, the ARL equivalent to how Java methods are processed. The rule engine is specified with the using parameter. The ability to imbed different rule engines with different control structures is key to any rules application. ABLE's implementation allows rule engines to be mixed within a ruleset, and for the creation and use of custom rule engines.

Next, notice the variable named count. Primitive variables and their corresponding object classes such as int and Integer are very different in ARL. There are no primitives in ARL, but the object equivalents are declared and manipulated as if they were primitives.

Finally, notice the modifier static on the Vector named list. In the ABLE Rule Language, static means that the variables’ value is static across ruleset executions. When the ruleset is to be run, it is first initialized which assigns variables to the values provided in the variables ruleset section. When the object parsed from these rules is first processed, rule p1 adds an item to list. Next rule p2 prints Count = 1 List.size()=1.

The AbleRuleSet object

The AbleRuleSet object is the core of the com.ibm.able.rules package. This object parses the text rulesets shown in the previous examples, and sets fields inside the object that represent the text ruleset. When the method process is called on an AbleRuleSet instance, the rules in the process ruleblock are run. There are other ruleblocks in addition to process that are described in Built-in ruleset sections.

The second time this ruleset is processed, list retains the element added in the first call because list is static. Count, however is not static so its value is reset to 1, the value assigned in the variables section. Thus after the second call, list will contain two items. The count of the number of times that the process ruleblock was called however, will still be printed as 1. Count must also be a static variable if it is to be used to count the number of times the process ruleblock is invoked. In Eclipse though, each time you run this ruleset, a new ruleset object is created so its variables will be reinitialized. But, when these rules are deployed, the process method can be called independently of initialization. The static modifier is used to differentiate which variables should retain values and which should be reset to their default declaration each time the process ruleblock runs.


Debugging a ruleset in Eclipse

You can use the Eclipse debug facility to step through rules and see the values for variables. In the JavaRuleSet1 ruleset, set a breakpoint on the first rule in the process ruleblock by double-clicking in the left margin. On the toolbar, select Debug > Debug… > ABLE RuleSet > New and create a launch configuration for the JavaRuleSet1 ruleset. Press Debug and ruleset execution pauses at the line you marked. You can step through rules or resume just as you can debug a Java program.

Check out the view labeled Variables and you see the global variables count and list as defined in the ruleset. You also see some other variables. These are built-in variables such as event, exception, inputBuffer, outputBuffer, parent, this, and wm. Built-in variables are described in Built-in ruleset sections in the ruleblocks where they are most often used.

Ruleset flow can be traced too, either to the console or to a file. Press Resume on the current ruleset launch if you haven't already done so. On the launch configuration panel, set the console trace level to medium. This time when you run the ruleset, the console view shows a ruleblock entry and exit and which rules are run. At a high level, results from a rule's clauses are added to what is shown at a medium level. Add a rule like p4: trace(“updated count"); at the end of the process ruleblock. User messages from the built-in trace method are displayed when trace is set to low, medium, or high information levels. After adding this rule and setting the trace level to low, updated count is the only console output.


Built-in ruleset sections

In both rulesets you've seen so far, you'll notice a ruleblock with a name of process. There are other named ruleblocks, each with a special purpose. One way to see a list of them is to use the New wizard to create an ABLE ruleset, selecting the complex type instead of basic. The example named ComplexRuleSet1 was generated this way. The built-in ruleblocks and code blocks you'll see include:

variables
variables is a section within the ruleset where global variables are defined and initially assigned. Each ruleset needs to have at least one global variable. Note too that individual ruleblocks can have their own variables block where local variables are defined.
inputs
inputs is a comma-separated list of global variables. This is an optional section used when the ruleset bean uses data buffer processing. When the ruleset object's process method is called, the first global variable is assigned the object in its inputBuffer array at element 0, the second global variable to the value at element 1, and so on.
outputs
outputs is similar to inputs. As the process method ends, the last step is to populate the outputBuffer. Element 0 is assigned to the first global variable in the outputs list, element 1 to the second, and so on.
init
init can be thought of as a static initializer. Rules in this optional ruleblock are evaluated just once, and after this ruleblock is run the ruleset is ready for use by any of the process ruleblocks. As a rule of thumb, consider that any variables set within this ruleblock should be defined as static variables. Another typical use is to set control parameters for ruleblocks such as the goal for ruleblocks that use backward chaining or any of the various parameters for fuzzy logic ruleblocks.
preProcess
preProcess is the first ruleblock called by the ruleset object's process method. This is an optional ruleblock typically used to do any work needed before the process ruleblock itself is called. Often it's convenient to have a procedural ruleblock using the Script engine to calculate intermediate values from variables supplied in the inputs list.
process
process is the second ruleblock called by the ruleset object's process method, and, as a required ruleblock, is typically the crux of the ruleset. Sometimes a process ruleblock will be a list of other ruleblocks to invoke.
postProcess
postProcess is the final ruleblock called by the ruleset object's process method. It is often a procedural ruleblock that sets values for variables in the outputs list or is used to print the results from the process ruleblock.
processAbleEvent
processAbleEvent is the ruleblock called when the ruleset object's event queue manager finds an event on its queue. All AbleObjects have an event queue that can be used for either synchronous processing on the caller's thread or asynchronous processing on a thread owned by the ruleset object. Typical logic in this ruleblock is to get the argObject from the built-in event variable, assign it to a global variable, and continue with script rules or invoke another ruleblock. The event itself, an instance of com.ibm.able.AbleEvent, determines whether it is to be handled synchronously or asynchronously. You can control whether events can be posted and whether they are processed with the setAbleEventProcessingEnabled API, and you might call that API from the init ruleblock with a rule like : this.setAbleEventProcessingEnabled(Able.ProcessingEnabled_PostingEnabled);.
processTimerEvent
processTimerEvent is the ruleblock called when the ruleset object's timer interval ends. All AbleObjects have a timed event capability. At the end of the time period this ruleblock is invoked. Typically, this is used for periodic reporting and for monitoring states and resource consumption. This ruleblock is run on the ruleset object's asynchronous thread. To use timed event processing, in the init ruleblock add rules like : this.setSleepTime(5000); and : this.setTimerEventProcessingEnabled(true);.
catch
catch is the ruleblock called when an exception occurs in any other ruleblock. This handles an unexpected condition and is especially useful to log errors when using timer or asynchronous event processing. The built-in variable exception contains the Java Exception object.
quitAll
quitAll is the ruleblock run when the ruleset object's quitAll method is called. This gives the ruleset author a chance to clean up before terminating.

Some uses of these different ruleblocks will be shown in later sections of this article. Of course, you can write as many additional ruleblocks as you want. Your ruleblocks can take parameters and return values as well.


An interactive ruleset

So far we've used only the Script inference engine, and we've embedded any data to be used within the ruleset itself. The ruleset DownLoadAssistantScript is just such a ruleset. If you know whether you plan to use the Eclipse platform, whether you prefer UNIX-style tar files, and whether you want local documentation for ABLE, processing this ruleset will list which of the ABLE download files on alphaWorks you need. It has a set of rules that are fairly straightforward:


Listing 3. Rules to determine which ABLE packages to download
  void process() { 
    helpEclipse: if (wantLocalDocumentation and eclipseDeveloper) 
             then docDownload = "com.ibm.able_v.r.m.bin.doc.dist.zip";
    helpWin: if (wantLocalDocumentation and !eclipseDeveloper and !unixUser)
             then docDownload = "doc.zip";
    helpUnix: if (wantLocalDocumentation and !eclipseDeveloper and unixUser)
             then docDownload = "doc.tar.gz";    
    helpNone: if (!wantLocalDocumentation) 
             then docDownload = "none";    
    agentDeveloper: if (unixUser) 
             then binDownload = "AbleAll_v.r.m.tar.gz";
             else binDownload = "AbleAll_v.r.m.zip";
    ruleDeveloper: if (eclipseDeveloper) 
             then binDownload = binDownload + ", com.ibm.able_v.r.m.bin.dist.zip";
  }

The values for the variables wantLocalDocument, eclipseDeveloper, and unixUser are all set in the variables ruleset section in the DownLoadAssistantScript ruleset. Instead of embedding the values in the ruleset, you'll create another ruleset that asks you how you intend to use ABLE, and use those values to deduce which download packages you need to install.

For this, you'll use the backward chaining inference engine. Backward chaining requires that there must be a specific goal assigned. In this control structure, the only rule antecedents (the left side of the rule) that are evaluated are those that are needed to find a value for that goal variable. If the consequent of a rule (the right side) sets the value for the goal variable, and its antecedent needs a value for a variable to fire that rule, the backward chaining inference engine can use the ABLE prompter to ask you to supply a value. The prompter is supplied by including the statement library com.ibm.able.rules.AbleGUILib;.

The DownloadAssistant ruleset shows prompting, backward chaining, using mixed inference engines in one ruleset, using the preProcess ruleblock, and invoking a ruleblock that you name. Try running it and examine the results. Because we're using backward chaining to prompt for data, each rule in the preProcess ruleblock includes all the variables to insure their values are provided by prompt.

The major difference between the DownloadAssistantScript and DownloadAssistant rulesets is the engine used to process the ruleblocks. The Script engine processes all the rules from top to bottom, and all the inputs must be provided, whereas the Backward chaining engine processes rules only until its goal variable is attained, and it can optionally prompt for inputs as needed. In a real application with a lot of rules you might provide values for all the variables and realize performance improvements from the control structure provided by backward chaining that reduces the number of rules fired.


Enhancing a ruleset

In many cases a simple procedural control strategy is all that is required. Business rule developers in particular seem to think that If-Then rules and top-down processing is sufficient for their needs. Over time, simple applications tend to become less simple, and then it's nice to have the capability to build on your existing application instead of starting a new one. ABLE lets you move to more advanced inferencing strategies as you need them, and this example shows one such scenario.

The first reaction to ABLE from many people is “Wow, there's a lot of function here. Where do I start?" Let's develop a ruleset that will help you decide what ABLE features might be useful in your application. Along the way, we illustrate how easy it is to convert from procedural to inferencing rules engines and you'll see how a forward-chaining rules-processing strategy can simplify your efforts.

Start with the FeatureAssistantScript ruleset where we define a list of potential uses for the ABLE technology in the variable expectedUse, and a list of possible tool recommendations in the variable recommendedTooling. Here you'll see a new data type, Categorical, which is a variable whose value must be one of a finite set of possibilities. Also note the Expression named rulesDeveloper, as shown in Listing 4. This provides a shorthand notation that allows you to reuse the same complex expression in multiple rules to make your rulesets more readable, encourage reuse, and simplify maintenance.


Listing 4. Expressions can simplify rules

Expression rulesDeveloper = (recommendedBeans.contains("DecisionTree Rule Engine")  
                            or recommendedBeans.contains("Script Rule Engine") 
                            or recommendedBeans.contains("Chaining Rules Engines" ));

Listing 5 shows the rule labeled ruleDeveloper, where this expression is used.


Listing 5. Expressions can be used in one or more rules too!

    ruleDeveloper: if (rulesDeveloper) 
             then recommendedTooling = "Both Swing and Eclipse";
             else recommendedTooling = "Swing";

Now, let's add the ABLE features that can be used in business rule applications. In addition to the features ABLE provides for simple rules, business rule developers would find Rule Preconditions and Rule Templates helpful. Rule preconditions let you define time periods during which a rule applies, and templates are useful for constructing rules from a rule pattern. Therefore, the FeatureAssistantBusinessRulesScript has one more expected use added (Business Rules), and the new rule is shown in Listing 6.


Listing 6. Adding a rule for Business Rules users in a procedural ruleblock

    doBusinessRules: if (workingUse == "Business Rules")
            then {
               recommendedBeans.add("Rule templates"); 
               recommendedBeans.add("Rule preconditions/timeperiods"); 
               recommendedBeans.add("Forward Rules Engine"); 
               recommendedBeans.add("DecisionTree Rule Engine"); 
               recommendedBeans.add("Script Rule Engine"); 
               recommendedBeans.add("Rule Expressions"); 
           }

Note that the last three topics added are the same topics used for the Simple Rules use. Now, say you're to add some other features that are helpful to simple rule developers. With the top-down, procedural scripting used to process this ruleblock, the easiest solution is to add these new features to both the lists in the rules doBusinessRules and doSimpleRules.

Wouldn't it be better to just add this in one place, and recognize that what is provided for users of Simple Rules would be useful in general to Business Rules? You can do that if you switch the rule engine used for the process ruleblock from the procedural Script engine to the Forward inferencing engine. Rather than duplicate the features for Simple Rules in two places, you can now just make the doBusinessRules rule read like Listing 7.


Listing 7. Adding more topics for Business Rules users in an inferencing ruleblock
    doBusinessRules: if (workingUse == "Business Rules")
            then {
               recommendedBeans.add("Rule templates"); 
               recommendedBeans.add("Rule preconditions/timeperiods"); 
               recommendedBeans.add("Forward Rules Engine"); 
               workingUse = "Simple Rules"; // add the beans for simple rules too!
           }

The forward chaining inference engine causes the rules to be re-evaluated, and first the doBusinessRules rule will fire. Because it changes the value for workingUse, when the rules are re-evaluated the doSimpleRules rule will fire. The forward inference engine evaluates assertion rules only once. Only conditional rules are re-evaluated, not rules unconditionally assigning variable values. Now, go back to the FeatureAssistantBusinessRulesScript ruleset, and change the label on the doSimpleRules rule to sourceOfFutureMaintenanceProblems so that you have truth-in-labeling.

To further illustrate the benefits provided by using an inferencing rule engine over a procedural rule engine, refer to the FeatureAssistant ruleset, where additional uses are added to the ruleset. If you'd like to try it the hard way, implement its rules using a procedural style and compare the performance, readability, and maintainability. Otherwise, run the FeatureAssistant ruleset to recommend ABLE features that will be of value for autonomic computing, resource balancing, diagnostics, planning, and policy management.


Using working memory in rulesets

Working memory is a repository used to store facts. Java programmers would see it as a hashset. When/do pattern matching rules use an ABLE feature called a selector to search working memory for objects of a specific Java class and with specified values. Selectors can detect either the presence or absence of such objects. Rules can add, remove, and modify facts in working memory. The inference engines that some people label artificial intelligence engines use working memory and are designed for applications that require more rules and variables. The built-in variable wm is the working memory container.

Listing 8 shows the rule used by the forward chaining engine for autonomic computing users.


Listing 8. The doAutonomic rule from the FeatureAssistant ruleset
    doAutonomic: if (workingUse == "Autonomic Computing")
            then {
               recommendedBeans.add("Machine Learning Beans");
               recommendedBeans.add("Composite Agents"); 
               recommendedBeans.add("Distributed Agents");
               workingUse = "Planning";
            }

What if the autonomic computing developers are interested in "Forecasting" and "Policy Management" in addition to "Planning"? This is easily done with the pattern match engine. Listing 9 shows the same rule from the FeatureAssistantRete ruleset.


Listing 9. The doAutonomic rule using pattern matching from the FeatureAssistantRete ruleset
    doAutonomic: when ( String task (task == "Autonomic Computing"))
            do {
               recommendedBeans.add("Composite Agents"); 
               recommendedBeans.add("Distributed Agents");
               wm.retract(task);
               wm.assertFact("Planning");
               wm.assertFact("Forecasting");
               wm.assertFact("Policy Management");
            }

As a user exercise, add another feature to the list called Inheritance and add that feature to the Business Rules item. Probably, you'll want to do this in the FeatureAssistantRete ruleset to save time, but if you're still convinced you don't need inferencing, add it to the FeatureAssistantBusinessRulesScript ruleset.


Extending a ruleset

If you're using Eclipse, select the FeatureAssistant and FeatureAssistantRete rulesets and select Compare to > Each other. Otherwise, just scan the two rulesets visually. See how similar these two rulesets are? You should notice that the rules in the preProcess and process ruleblocks are different, but otherwise the rulesets are nearly identical. Primarily what FeatureAssistantRete does is represent the rules in the FeatureAssistant ruleset's process ruleblock as When/Do pattern matching rules.

Now compare FeatureAssistant to FeatureAssistantExtended. Notice how the latter ruleset extends the former? You don't need to repeat the variable definitions, and you don't need to repeat all the rules. All you do is override the rules in the preProcess and process ruleblocks that are necessary. Rules in ruleblocks with identical names are merged, and rules of the same name replace those in the base ruleset. Sorry, but the Eclipse ARL editor doesn't yet support the ARL extends feature.


Providing data to a ruleset

There are actually three different ways provided to pass data to an ABLE ruleset. The most basic way is to pass data to the ruleset directly using the ABLE data buffer design to set variables and to retrieve results. The FeatureAssistantApp Java class shows how to construct a ruleset, parse the contents of one of the text files we've been discussing, and demonstrates using it to set inputs and retrieve the results. In this example, we provide the value for expectedUse directly instead of using the preProcess ruleblock to prompt for it. To run this class requires able.jar, ablerules.jar, ablegui.jar, JLog.jar, and antlr.jar in the classpath, and you will need to change the ruleset path.


Listing 10. Running a ruleset as an application
   public static void main(String[] args) {
   	 try {
        AbleRuleSet ruleSet = new AbleRuleSet();
        ruleSet.parseFromARL("C:\\developerworks\\ac-able2source
                                           \\FeatureAssistantExtends.arl");
        ruleSet.init();
        ruleSet.addVariableToInputSequence("expectedUse");
        ruleSet.addVariableToOutputSequence("recommendedBeans");
        Object[] output = 
                     (Object[]) ruleSet.process(new String[]{"Autonomic Computing"});
        Collection recommendedBeans = (Collection)output[0];
        System.out.println(recommendedBeans);
   	 } catch (Exception exp) {
   	 	System.out.println(exp.getLocalizedMessage());
   	 	exp.printStackTrace();
   	 }
     System.exit(0);
  }

Notice we add the input and output variables to the ruleset because the FeatureAssistantExtends ruleset defines no input or output variables.

Data can also be provided by using the ruleset as an event listener, or using an API by getting a reference to a ruleset variable and setting its value directly. These techniques will be described in a later developerWorks article. There are examples and documentation describing them in the existing alphaWorks download.


Periodic and seasonal rules

So far we've shown ARL rules as similar to Java code; there's a trailing semicolon, and there's an optional label preceding a required colon used to identify the rule. Additional rule metadata can also precede that colon. That metadata can be used as a switch to include or exclude a rule from evaluation within a ruleset. This capability is particularly useful when providing business and policy rules.

Open the FeatureAssistantExtendsTimePeriod ruleset. This ruleset is another extension from the FeatureAssistant ruleset. It includes some friendly reminders and states the current version of ABLE available for download based on the time the ruleset is run. The ruleset defines some TimeStamp and TimePeriod variables and adds these rules to the showResults ruleblock in the ruleset it extends:


Listing 11. Rules with precondition metadata

  void showResults() {
    RuleMorning {morning} : println("Good morning!");
    RuleAfternoon {afternoon} : println("Good afternoon!");
    RuleEvening {evening} : println("Good evening!");
  	
    RuleLastDay {lastDay} : println("On the last day of every month check for a 
                                    new release of ABLE.");
    RulePayDay  {payDay}  : println("Payday is the first and fifteen of each 
                                    month.");
    
    RuleDownload      : println("The most recent ABLE release is:");
    Rule2_0 {able2_0} : println("Able 2.0 has major improvements to the rule language 
                                and Eclipse-based tooling.");
    Rule2_1 {able2_1} : println("Able 2.1 has planning, policy, and decision tree rule 
                                engines.");
    Rule2_2 {able2_2} : println("Able 2.2 has HTN planning, ruleset inheritance, rule 
                                merge and replace.");
    Rule2_3 {able2_3} : println("Able 2.3 is based on JDK 1.4 and Eclipse 3.0, and is 
                                now available!");
  }

The metadata is provided by variables within the curly braces, and those variables are declared in the variables ruleset section like shown in Listing 12.


Listing 12. Defining time periods to use in rule preconditions
  variables {
    Long lastDay = ARL.LAST_DAY_1;  
    Long payDay = ARL.DAY_1 + ARL.DAY_15;  

    TimeStamp start = new TimeStamp("01/01/1999 12:00 AM");
    TimeStamp end   = new TimeStamp("01/01/2024 12:00 AM");   
    TimeStamp now = new TimeStamp();  

    TimeStamp able2_0Release = new TimeStamp("07/07/2003 12:00 AM"); 
    TimeStamp able2_1Release = new TimeStamp("04/01/2004 12:00 AM");
    TimeStamp able2_2Release = new TimeStamp("02/01/2005 12:00 AM");
    TimeStamp able2_3Release = new TimeStamp("04/01/2005 12:00 AM"); 

    TimePeriod able2_0 = new TimePeriod(able2_0Release, able2_1Release); 
    TimePeriod able2_1 = new TimePeriod(able2_1Release, able2_2Release); 
    TimePeriod able2_2 = new TimePeriod(able2_2Release, able2_3Release); 
    TimePeriod able2_3 = new TimePeriod(able2_3Release, end); 
   
    TimePeriod morning   = new TimePeriod(start, end, "12:00:00 AM/11:59:00 AM") ; 
    TimePeriod afternoon = new TimePeriod(start, end, "12:00:00 PM/04:30:00 PM") ; 
    TimePeriod evening   = new TimePeriod(start, end, "04:30:01 PM/11:59:00 PM") ; 
  }

We force the metadata to be evaluated each time the ruleset is processed by adding two rules to the preProcess ruleblock, as shown in Listing 13.


Listing 13. Evaluate rule metadata before processing data
  void preProcess() using Backward {
     checkTime: now = new TimeStamp() ; 
     setMetaData: this.checkTimePeriodPreConditions(now) ;  
  } 


Summary

We've shown only the tip of the iceberg with respect to the features provided in the ABLE Rule Language. Look for future articles on additional inference engines that use fuzzy logic and pattern matching and on ARL constructs such as arrays, expressions, extending rulesets, inner classes, OCL collections, overriding rules and merging ruleblocks, predicate logic, rule preconditions and priorities, switch statements, templates, time period variables, and working memory, as well as using the APIs in the com.ibm.able.rules package. If you can't wait for the next developerWorks article, there is an ARL language reference, and there are over 50 example rulesets available in the download from alphaWorks.

The ABLE Rule Language provides a Java-like syntax in which simple If-Then rules can readily be written. Deciding what logic to express in rules is not an easy task. Like any IT application, start small with simple, achievable goals, and extend and grow it over time. You won't need all the features of the ABLE Rule Language in your first application using rules. As the project grows in complexity, more complex rule forms and more powerful reasoning algorithms are available in ARL. Rather than changing technologies, you've seen that with ARL you can build on that first rules application, adding rules and applying new inferencing engines as your needs evolve.

You can contact the ABLE development team at ableinfo@us.ibm.com. Let us know what you think of this article and which of the additional features of ARL you'd like to see described in a future developerWorks article.



Download

DescriptionNameSizeDownload method
Ruleset and Java examples used in this articleac-able2source.zip16 KBHTTP

Information about download methods


Resources

About the authors

Jeff Pilgrim is an Advisory Software Engineer assigned to the ABLE research team at IBM eServer Software Services in Rochester, Minnesota. His previous development experience includes work on Intelligent Miner for Data, Neural Network Utility, wide area wireless computing, and systems management. He was a developer and architect for several system configurators, as well as for numerous internal industrial engineering applications. Jeff originally joined IBM at its Federal Systems Division in Owego, NY, where he was responsible for forecasting workload for defense contracts. He holds a Master of Science degree in Industrial Engineering and Operations Research from the Pennsylvania State University.

Joe Bigus is a Senior Technical Staff Member at the IBM T. J. Watson Research Center, where he is the project leader on the ABLE research project. He is a member of the IBM Academy of Technology and is an IBM Master Inventor, with over 20 U.S. patents. Dr. Bigus was an architect of the IBM Neural Network Utility and Intelligent Miner for Data products. He received his M.S. and Ph.D. degrees in Computer Science from Lehigh University and a B.S. in Computer Science from Villanova University. He has written two books: Data Mining with Neural Networks (McGraw-Hill) and Constructing Intelligent Agents with Java (Wiley). Dr. Bigus's current research interests include learning algorithms and intelligent agents, as well as multiagent teams and their applications to adaptive system modeling and control, data mining, and decision support.

Don Schlosnagle is an Advisory Software Engineer at IBM eServer Software Services in Rochester, Minnesota. He studied computational linguistics and expert systems at SRI and wrote, in Common Lisp, a PC-based natural language DB2 query program that was successfully marketed by IBM as a PRPQ. Mr. Schlosnagle has since worked on the Neural Network Utility and on Intelligent Miner for Data, where he contributed the fuzzy logic inference system for evaluating proposed neural network architectures. A greatly enhanced version of the fuzzy system found its way into ABLE. Mr. Schlosnagle's current interest is in combining neural networks with fuzzy logic.

Any of the authors can be contacted by e-mail through ableinfo@us.ibm.com.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in

If you don't have an IBM ID and password, register here.


Forgot your IBM ID?


Forgot your password?
Change your password


By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. This profile includes the first name, last name, and display name you identified when you registered with developerWorks. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)


By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Tivoli
ArticleID=47194
ArticleTitle=Adding rules to applications
publish-date=02152005
author1-email=
author1-email-cc=
author2-email=
author2-email-cc=
author3-email=
author3-email-cc=

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).