RiverSoftAVG Newsletter #4
Hello and welcome to the fourth edition of RiverSoftAVG's newsletter! It is amazing how the year is flying by. This latest newsletter may be a little late but it is the best one yet! In this issue, we reveal exciting details about the database support that will be in the upcoming Inference Engine Component Suite (IECS) version 2. Also, we have two tips for writing your expert systems, one from the coding side and one from the expert system side. Finally, we thought you should know about a new free component to download (in case you haven't been to the web site lately)!
A reminder, this newsletter and all previous ones are available for download from the web site at http://www.riversoftavg.com/articles_&_tips.htm
Note: You received this newsletter because you are an owner of a RiverSoftAVG product. If you received this newsletter by mistake or if for any reason you wish to not receive any future mailings from RiverSoftAVG, just reply to this message informing us so. We apologize for any intrusion.
This Fall, the Inference Engine Component Suite (IECS) is going to receive a major upgrade, bringing it up to version 2.0. While this will not be a free upgrade (pricing to be determined), we think that this upgrade will be well worth it. This month, we will discuss one of the great new features coming in version 2.0, database support. In later newsletters, we will have more about other great features to come.
One of the major new features for the IECS will be database support (for Delphi Pro and above users, of course). The new database features of the IECS are incredibly integrated and transparent. Basically, if you have used the Delphi database components before, you will know how to use these. For version 2, we are making a data-aware inference engine descendant, TDBInferenceEngine, which is much more powerful than standard data-aware controls. The TDBInferenceEngine component provides two powerful database features for your expert systems:
Let's talk about the first feature. The TDBInferenceEngine component accepts multiple datasources and multiple fields from each datasource. Unlike traditional data-aware controls (TDBEdit, TDBMemo) which accept one dataset and usually only one field in the dataset, the TDBInferenceEngine component can read from and write to multiple datasources. Each data source defines a different fact template in the inference engine, and each field of the data source can be mapped to a slot in the fact template. At run-time, each record in the data source defines, or relates to, a fact. As the user or program scrolls around the dataset, new facts are automatically asserted to and retracted from the inference engine.
For example, the BioLife table in the DBDEMOS database defines 8 fields: Species No, Category, Common_Name, Species Name, Length (cm), Length_In, Notes, and Graphic. The TDBInferenceEngine component supports fields with primitive types: integer, float, etc (sorry, no blobs). The IECS architecture automatically maps this table as a fact template in the expert system; each allowable field maps to one slot in the fact template (you can specify which ones). Each record, as the dataset moves to it, is asserted onto the fact list of the inference engine. By default, when the dataset leaves the record, the equivalent fact is retracted from the inference engine. Note that retractions, again by default, will not delete records in the dataset (deleting records when retractions occur could be a disastrous side effect, for example, when you clear the inference engine).
Now let's go through the steps so you can see how really easy it truly is:
(deftemplate Table1 "Dataset facts"
(slot SpeciesNo (type INTEGER FLOAT) (default "90020") )
(slot Category (type ATOM STRING) (default "Triggerfish") )
(slot Common_Name (type ATOM STRING) (default "Clown Triggerfish") )
(slot SpeciesName (type ATOM STRING) (default "Ballistoides conspicillum") )
(slot Length_In (type INTEGER FLOAT) (default "19.6850393700787") )
(slot Lengthcm (type INTEGER FLOAT) (default "50") )
f-1 (Table1 (SpeciesNo 90110) (Category "Shark") (Common_Name "Swell Shark") (SpeciesName "Cephaloscyllium ventriosum") (Length_In 40.1574803149606) (Lengthcm 102))
For a total of 2 facts.
while not Table1.Eof do
while not Table1.Eof do
Now, what does it mean "it can act like a database, where every fact template can be a dataset, for other data-aware controls?" The TDBInferenceEngine component can also make the connection the other way. The inference engine acts as a virtual database. Using a special TIEDataSet component, you can connect to the TDBInferenceEngine component. From there, a TDataSource component can link to the dataset, and data-aware controls can link to the data source. But what does this feature mean to you? Well, now you can use standard Delphi data-aware controls, such as TDBGrid, to edit, assert, and retract facts from the engine. Your user (or you) need not know any CLIPS! As a bonus, by making the IE data-aware and act like a database at the same time, you can chain IEs together. IE1->TIEDataset->TDataSource->IE2!
The database support is rounded out in the IECS by supplying functions so that you can work with these new features from within your expert system. For example, an 'assert-record' function is now available that will not only assert your fact into the inference engine, but if the fact template is mapped to a dataset, will also post a record.
This is only a quick explanation of the new database features in the IECS. Hopefully, it has whetted your appetite for version 2.0. In the coming months, we will discuss other features of this major upgrade.
Many times, you may want to write an expert system where only certain rules should be considered at certain time. For example, you may want to write rules that only fire during some initialization phase, other rules to fire when an expert system is "reasoning", and finally, some rules at the end to clean up. What you are looking for is some way to control the flow of execution in the expert system, to partition your rule set.
To partition your rule sets is very easy. You define a special phase, or flow-of-control, fact type, which is used as a pattern on the left-hand-side of your rules to control their activations. For example, say you wanted to have three periods in your expert system: init, reason, and cleanup. To write rules that would only execute in the reason period, you would include the (phase reason) fact in your rule:
(deftemplate citizen (slot name) (slot status))
(citizen (name ?name) (status good))
(printout t ?name " is a good citizen"))
To implement your flow of control automatically, e.g., to change phases, you need a fact set (or deffacts in CLIPS terminology) and a "phase change" rule. The fact set specifies the phase fact and enumerates all the phases using some "next-phase" facts. The phase change rule is a rule with a really low priority so that it only fires if no other rule can fire. If the phase change rule fires, it automatically advances the phase to the next phase in the enumeration.
; Fact Sets
(deffacts phase-factset ""
(next-phase init reason)
(next-phase reason cleanup)
"Change phases if no other rules can fire"
(declare (salience -10))
?p <- (phase ?phase)
(next-phase ?phase ?next-phase)
(assert (phase ?next-phase)))
Often in expert systems, you will find yourself writing rules which have variables. Variables match facts against a certain pattern and then work with that specific fact's information in the right hand side of the rule. For example,
(citizen (name ?name) (status good))
(printout t ?name " is a good citizen"))
?name is a variable. When the inference engine finds a citizen fact that matches to "status equals good", this rule will be activated. Using the ?name variable, you can access the fact's name slot value on the right-hand-side of the rule, such as with the printout function above.
Well, that is all well and good when you are writing rules in CLIPS, but how do you access variables from within a rule's OnFire event, using a TRule component at design-time? When the OnFire event is called, your event handler gets two parameters: Sender (which is the rule) and Context. It turns out Context is the key to getting rules from your code. The TIEContext object is how the inference engine library defines scope within an expert system. Just like in Object Pascal, where you can have global variables which can be hidden by local variables within a function or method, so too does the inference engine have global and local variables. The scoping is controlled through TIEContext objects. There is a global context (GlobalContext property) for the inference engine. Every rule firing also gets a local context which will contains the variables defined only for that rule (such as the ?name variable above).
You use the Variable property of the TIEContext class to access variables. The Variable property accepts the name of variable (without the question mark) and returns its value (IIEValue interface).
So, to write the above rule as a design-time rule, we would use the following steps:
procedure TMainForm.Rule1Fire(Sender: TObject; Context: TIEContext);
InferenceEngine1.PrintOut( Context.Variable['name'].AsString + ' is a good citizen.' );
In January, we made available for download from our web site a free Flocking component. Last month, we extended the flocking components to implement group formations! These new components move your little boids into squares, wedges, etc like they are on a parade ground! :) If you haven't already downloaded it, you should get it as it really is an amazing display of emergent behavior. The demo comes with source and executable for testing the flocking code. It demonstrates how to implement formations using flocking behavior. The formation flocking code is based on the four rules of flocking: separation, alignment, cohesion, and avoidance. The Formation Flocking code however modifies the standard cohesion and separation rules to provide formations. The cohesion rule now moves the boid towards its position in the formation rather than toward the flock's center point. The separation rule has been modified so that it doesn't interfere when the boid is in its place in formation. In addition, the separation strength has been turned way down to avoid the boids from pushing away from each other in the formation.
You can find the Formation Flocking component at http://www.riversoftavg.com/formation_flocking.htm
Send mail to
webmasterNO@SPAMRiverSoftAVG.com with questions or comments about this web