Frequently Asked Questions
***************************************************************
IECS
Q: Where can I
find documentation/examples about CLIPS?
Q: I've always programmed in Turbo
Pascal. Now, I need to use an expert system that runs under Delphi. I installed
the IECS but don't know how to start. Is there a manual? Any tips?
Q: My zip file didn't come
with Help!
Q: My zip file
didn't come with any demo projects!
Q: When I do a "Build All", Delphi fails with a Internal compiler error.
Q: How can I define an OnFire
event at design-time that can be used with an expert system that I load at
run-time?
Q: I install TeeChart pro
XX for Delphi, but it does not work with the evaluation version of the IECS.
What can I do?
OICS
Q: Can it inspect public properties? How do you create fake properties?
Q: I want to inspect my own objects. Can the inspector inspect any TObject
descendent, as long as it exposes properties? Does it require that inspected
objects descend from a given base class?
Q: Is is possible (easy) to choose to only display properties that are different
between the objects being compared?
Q: Does your object inspector require a component with published properties?
Or, can you assign a pretend "object name" and add the properties by hand?
Q: Where can I
find documentation/examples about CLIPS?
A: CLIPS documentation in PDF and Postscript format can be found athttp://www.justme.com/~CLIPS/
A CLIPS forum is at
http://www.cpbinc.com/clips/viewforum.php?f=1
Q: I've always
programmed in Turbo Pascal. Now, I need to use an expert system that runs under
Delphi. I installed the IECS but don't know how to start. Is there a
manual? Any tips?
A: It depends on how much experience you have with expert systems. There are
demos of working with the IECS, included in the IECS. Look in the demos
directory. There are also example expert system files in the scripts directory.
Also, there is an expert system wizard, which helps walk you through developing
an expert system. If you drop the TInferenceEngine component on a form,
right-click it, and select "Start Expert System Wizard..." that may help you. As
far as the "language," it is a CLIPS derivative (seeCLIPS Compatibility). The help files
discuss every function the IECS implements. If you wish more general information
about CLIPS, there is a PDF at
http://www.justme.com/~CLIPS/ Finally, the book, Expert Systems:
Principles and Programming discusses expert systems and CLIPS.
Q: My zip
file didn't come with Help!
A: The help files are packaged separately. Please download the help files for
your version of Delphi from the
www.RiverSoftAVG.com\downloads.htm
Q: My zip file
didn't come with any demo projects!
A: You must have downloaded the demo version of the Inference Engine Component
Suite. Please download the IEHelp and the IEDemoProjects zip files for your
version of Delphi from the
www.RiverSoftAVG.com\downloads.htm
Q: When I do a "Build All", Delphi fails with a Internal compiler error.
A: This error occurs in Delphi 4, 5, 6, & 7 and in their own words:
"You should never get this error message - it means there is a programming error
in the compiler. "
Unfortunately, we have been unable to discover the exact code that causes Delphi
to get upset. Fortunately, this error is easy to get around. Delphi "almost"
finishes the Build All. After you see this error, just Compile the project
normally. (No build all). Everything will have been recompiled and is ready and
correct.
Q: How can I
define an OnFire event at design-time that can be used with my expert system
file? I wish to load a file containing multiple facts and rules into the
TInferenceEngine Component and then use use an OnFire event handler for one of
these loaded rules. As I understand it only the TRule component has an OnFire
event and TRule is suitable for defining one integral rule at a time and a
LoadFromFile call will overwrite this anyway.
A: There are few ways to do what you want to do. First, I assume you have a
TInferenceEngine component and a TRule component with OnFire event defined.
Also, you have in your code somewhere the LoadFromFile statement:
InferenceEngine1.LoadFromFile( OpenDialog.FileName );
1. After loading your expert system from file, you can add the design-time rule
back into the inference engine:
InferenceEngine1.LoadFromFile( OpenDialog.FileName );
InferenceEngine1.Rules.Add( Rule1 );
Note that you either need to have a unique rule name or the
InferenceEngine1.DuplicateConstructs property must be set to dcOverwrite.
2. The TRule events are all available at runtime as well. After loading your
expert system from file, you can assign your design-time event to the rules in
the inference engine:
InferenceEngine1.LoadFromFile( OpenDialog.FileName );
InferenceEngine1.Rules['clear-upper-block'].OnFire := Rule1.OnFire;
3. Of course, you can always create a TInferenceEngine.OnRuleFired event handler
and check if the rule that fired is the one you want to take some action with
(This is not recommend as this event gets called when EVERY rule fires, not just
the one you want):
procedure TMainForm.InferenceEngine1RuleFired(Sender: TObject;
Rule: TRule);
begin
if Rule.RuleName = 'clear-upper-block' then
ShowMessage( Rule1.RuleName + ' fired' );
end;
Q: I
install TeeChart pro XX for Delphi, but it does not work with the evaluation
version of the IECS. What can I do?
Unfortunately, the demo does not support different TeeChart (the IEDclDXX
package requires the Tee package). With the registered versions of the IECS,
you could of course change the IEDclDXX package to use the TeeXX instead of the
standard Tee package that comes with Delphi. Note that this answer
discusses IECS v2.13 and earlier. The latest version of the IECS no longer
uses TeeChart.
Q: Can the OICS inspect public properties? How do you create fake properties?
A: The OICS uses RunTime Type Information (RTTI) to access the properties of
a
class - so, no, *public* properties are not available automatically (this is
true of any object inspector component, including Borland's) However, the
OICS makes it VERY easy to add calculated (fake) properties that can access
and modify underlying public properties. The TStringsCountExample in the
evaluation demo shows how easy it is by adding a calculated property for the
public Count property of a TStrings class.
Basically, you do three things, create the property item and then create
event handlers for getting (reading from TStrings.Count) the property and
setting (writing to TStrings.Count) the property:
procedure TForm1.RSObjectInspector1AfterScan(Sender: TObject;
const Item: TRSItemProperty);
begin
if (Item <> nil) and (Item.TypeName = 'TStrings') then
with Item.Items.Add('Count','') do
begin
OnGetProperty := RSObjectInspector1Presets19GetProperty;
OnSetProperty := RSObjectInspector1Presets19SetProperty;
end;
end;
procedure TForm1.RSObjectInspector1Presets19GetProperty(Sender: TObject;
const Instance: TObject; const PropName: String; var Value: String);
begin
Value := IntToStr(((Sender as TRSItemProperty).Parent.GetObjectProperty
as TStrings).Count);
end;
procedure TForm1.RSObjectInspector1Presets19SetProperty(Sender: TObject;
const Instance: TObject; const PropName, Value: String);
var
NewCount: Integer;
begin
NewCount := StrToInt(Value);
with (Sender as TRSItemProperty).Parent.GetObjectProperty as TStrings
do
begin
if Count = NewCount then Exit;
while NewCount < Count do
Delete(Count-1);
while NewCount > Count do
Add('');
(Sender as TRSItemProperty).Editor.InvalidateScan;
end;
end;
Q: I want to inspect my own objects. Can the inspector inspect any TObject
descendent, as long as it exposes properties? Does it require that inspected
objects descend from a given base class?
A: To automatically inspect objects, the object must have RunTime Type
Information (RTTI). Therefore, your objects need to descend from TPersistent OR
you use the {$TYPEINFO ON} compiler flag in the declaration of your class.
Q: Is is possible (easy) to choose to only display properties that are different
between the objects being compared?
A: For inspecting multiple objects, the two objects must share the same
property (e.g., if Object1 has a Font property and Object2 does not, Font will
not appear in the object inspector). Now, if they do share the same property,
you can easily only display properties that have different *values* between the
two.
Basically, Create a custom preset (actions = [custom])that matches any property
(MatchType = [mtPropertyType]) and (TypeKind = [tkUnknown]). When it matches,
the OnCustomPreset event of the preset will execute. In the event, make any
property that has the same values invisible:
Item.Visible := Item.Values[0] <> Item.Values[1];
Note that this example works for two objects only, but it is easy to see how to
scale it for multiple items
Q: We have a project that has no TComponent-based
objects in it whatsoever, yet we have a need to edit some pseudo-objects with
pseudo-properties.
Does your object inspector require you to assign a component with published
properties (or with the calculated properties you mention in your release
notice)? Or, can you assign a pretend "object name" and add the properties by
hand?
The OICS would definitely do what you want. The OICS can accept
TComponents with published properties, it can accept TPersistents with published
properties, and you can build a pseudo-object with pseudo-properties from
scratch. Here is an example using the base class, TRSItemListEditor. You can
verify this yourself with the evaluation version. This example creates a pseudo
property that maps to the form's font.name underneath:
procedure TForm1.FormCreate(Sender: TObject);
begin
with RSItemListEditor1.Items.Add do
begin
Name := 'My Pseudo Property which is a font';
Value := Font.Name;
end;
end;
procedure TForm1.RSItemListEditor1GetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
// Use the row to figure out the item being edited... since we only have
// one item we don't have to do that.
Value := Font.Name;
end;
procedure TForm1.RSItemListEditor1Validate(Sender: TObject;
Item: TRSItemProp; ACol: Integer);
begin
// user has changed the value. Update Font.Name
Font.Name := Item.Value;
end;
Here is another example using the TRSObjectInspector where we add a pseudo
property to the list of properties for a bit button:
procedure TForm1.FormCreate(Sender: TObject);
begin
RSObjectInspector1.Component := BitBtn1;
end;
procedure TForm1.RSItemListEditor1GetEditText(Sender: TObject; ACol,
ARow: Integer; var Value: String);
begin
// Use the row to figure out the item being edited... since we only have
// one item we don't have to do that.
if (TRSObjectInspector(Sender).VisibleItemCount > 0) and
(TRSObjectInspector(Sender).VisibleItem[ARow-TRSObjectInspector(Sender).FixedRows].Name
= 'My Pseudo Property which is a font') then
Value := Font.Name;
end;
procedure TForm1.RSItemListEditor1Validate(Sender: TObject;
Item: TRSItemProp; ACol: Integer);
begin
// user has changed the value. Update Font.Name
if Item.Name = 'My Pseudo Property which is a font' then
Font.Name := Item.Value;
end;
procedure TForm1.RSObjectInspector1AfterScan(Sender: TObject;
const Item: TRSItemProperty);
begin
if Item <> nil then Exit;
// Item equals nil, we are finished completely scanning the object
with RSObjectInspector1.Items.Add do
begin
Name := 'My Pseudo Property which is a font';
Value := Self.Font.Name;
end;
end;