Beating HeaRT
Docs
More docs available upon request from the author: wojnicki@agh.edu.pl.
Concept
Starting inference process
The inference process must be explicitly started from an indicated XTT table by using run_xtt_single/1
predicate:
run_xtt_single(xtt_0).
The engine triggers appropriate I/O routines to provide attribute values (for ro
or rw
class attributes present in the conditions),
it comes up with a conflict set (a set of rules for particular XTT which conditions are met),
resolves it (see below) and
fires appropriate rules in turn,
triggers appropriate I/O routines (for all wo
or rw
class attributes present in the decisions),
switches to the next XTT associated with the fired rules.
The inference process ends if there are no rules to fire (fails), or if the last fired rule has no outgoing links (succeeds).
For future releases it might be desired to have an algorithm which finds which XTT should the inference process start with.
It could be an XTT without incoming links, however it is still subject to further research.
Conflict set resolution
The conflict set is built with rules which conditions are met.
It is resolved in the following way:
if the rule has no outgoing links add it to the resolved set,
if there is a rule with an outgoing link/links add it to the resolved set and stop the conflict set resolution.
I/O
Appropriate trigger routines are called for ro
, rw
, wo
class attributes.
To define a routine a predicate io/3
is used:
io(att_12,ro_trigger,get_character).
io(att_10,wo_trigger,write_chars_to_file).
The above defines that an attribute with unique identifier att_12
has a routine get_character/1
defined which will be spawned before reading attribute value (the attribute is ro
or rw
class).
Furthermore att_10
has write_chars_to_file/2
which will be spawned after the rule, with such an attribute in the condition part, is fired.
Comparing to the original idea (hekate_prolog_io) there is a slight adjustment. Attribute values are passed to/for the trigger routines as list.
Attribute values are passed as lists, single element list for single valued attributes, multiple element list for multiple valued attribute. See example below.
Avaliable operators
The following operators are defined in operators.pl
file.
The implementation is far from being complete, just a few operators are defined at present to cover the editor case .
These operators are used in editor-model.xttml
.
Evaluative
add – evaluates to a sum of 1st and 2nd argument
sub – evaluates to a difference of 1st and 2nd argument
insert – inserts a value into a multivalued attribute at given index
remove – removes a value from a multivalued attribute at a given index
Logical
eq – checks for equality
neq – checks for inequality
in – checks if 1st argument is within a set
nin – checks if 1st argument is not within a set
gt – geater than (available from release-2)
lt – less than (available from release-2)
Modification
Availability
Current development vresion:
cvs -d :ext:charon.ia.agh.edu.pl/mnt/cvs/cvs-hades co bheart
Releases:
Second release, thermostat case added, more logical operators (to make the thermostat case work)
bheart-rel-2.tar.gz
cvs -d :ext:charon.ia.agh.edu.pl/mnt/cvs/cvs-hades co -r rel-2 bheart
cvs -d :ext:charon.ia.agh.edu.pl/mnt/cvs/cvs-hades co -r rel-1 bheart
Modules
The inference engine is highly modularized.
It consists of the following modules:
hml.pl - Hekate Markup Language (
HML1) support
infeng.pl - inference engine
operators.pl - available operators
prolog-runtime.pl - prolog i/o predicates
runtime.pl - auxiliary runtime predicates
hml-view.pl - HML visualization support (markup independent), not mandatory for run-time execution; spawns graphviz and generates XTT diagrams (yet to be released, avaliable through CVS only)
This way the Beating HeaRT can be extended easily.
I/O Modules
There are two I/O modules currently available for the Inference Engine.
They allow to call apropriate trigger routines for non-state attributes which are implemented as Prolog predicates or Java methods.
Examples
Editor
The following example is included in the Beating Heart in a file: test-bheart.pl
.
It provides logic for a simple text editor.
The editor is capable of reading in characters into a buffer (chars
) which contents is displayed at any change (chars
is wo
class) along with the value of cursor
attribute, which represents cursor position.
There are following key sequences covered by the rules:
^o – open a file, currently it resets the buffer (implemented by read_chars_from_file/1
predicate),
^s – save – displays current contents of the buffer (implemented by write_chars_to_file/2
),
backspace – obvious,
^j – moves the cursor left,
^k – moves the cursor right,
^q – quits.
The XTT editor model is given below (click to enlarge).
The model is generated by the Beating HeaRT visualization plugin.
The following code, loads up The Beating HeaRT, reads in logic, defines all I/O routines for apropriate attributes and launches the inference process.
:- [bheart]. % consulting the Beating Heart
%:-assert(bheart(debug)). % to enable b heart debugging
:-hml_load('editor-model.xttml'). % loading up model.
% defining i/o routines
% general i/o
% inkey
io(att_12,ro_trigger,get_character).
% inchar
io(att_8,ro_trigger,read_chars_from_file).
% outchar
io(att_10,wo_trigger,write_chars_to_file).
% editor content output
% chars:
io(att_3,wo_trigger,display_chars).
% cursor
io(att_4,wo_trigger,display_cursor).
% single character input
get_character([Char]):-
get_single_char(C),
resolve_character(C,Char),!.
resolve_character(15,"^o").
resolve_character(19,"^s").
resolve_character(17,"^q").
resolve_character(10,"left").
resolve_character(11,"right").
resolve_character(127,"backspace").
resolve_character(C,[C]).
% editor content output
display_chars(X,X) :-
write('on screen->>>:'),maplist(putvalues,X),nl.
display_cursor([X],[X]):-
write('cursor at->>>:'), write(X),nl.
% file i/o
read_chars_from_file(["T","h","i","s"," ","i","s"," ","r","e","a","d"," ","i","n","."]).
write_chars_to_file(X,X):-
write('file output->>>:'),maplist(putvalues,X),nl.
putvalues([]):-
put(' ').
putvalues([13]):-
nl.
putvalues([X]):-
put(X).
% starting the inference process
:-run_xtt_single(xtt_0).
Thermostat
The following example is included in the Beating Heart in a file: test-therm.pl
.
It is a famous thermostat example.
The actual XTT differs slightly from the one presented in hekate_case_thermostat.
The original thermostat XTT model is given below:
There is a question to be asked: which rules should be interpreted first, these from table id 1, or these from table id 2 ?
To eliminate such an ambiguity an alteration is performed which results in the following XTTs:
Now it is easy to assume that the inference process hsould start with Table id 1.
The following visualization is generated by the Beating HeaRT visualization module.
The following code, loads up The Beating HeaRT, reads in logic, defines all I/O routines for appropriate attributes and launches the inference process.
Since input has to be delivered to the inference engine, it spawns appropriate I/O routines to get actual month, hour, and day of week.
:- [bheart]. % consulting the Beating Heart
%:-assert(bheart(debug)). % to enable b heart debugging
:-hml_load('therm-model.hml'). % loading up model.
% defining i/o routines
% day
io(att_7,ro_trigger,get_day).
% month
io(att_8,ro_trigger,get_month).
% hour
io(att_10,ro_trigger,get_hour).
% thermostat_settings
io(att_11,wo_trigger,set_temperature).
get_day([Day]):-
write('Day of week (in double quotes, ending with period: "tue".):'),
read(Day).
get_month([Month]):-
write('Month (numeric):'),
read(Month).
get_hour([Hour]):-
write('Hour (numeric):'),
read(Hour).
set_temperature(X,X) :-
write('temperature->>>:'),write(X),nl.
% starting the inference process
:-run_xtt_single(xtt_0).