NAME
Chorus::Engine - A very light inference engine combined with the frame model for knowledge representation.
VERSION
Version 1.04
INTRODUCTION
Chorus-Engine makes possible to simply develop in Perl with an Articial Intelligence approach
by defining the knowledge with rules the inference engine will try to apply on your objects.
Because inference engines use to waste a lot of time before finding interesting instanciations
for rules, the property _SCOPE is used to optimise the space on which each rule must be tested.
This not necessary but, uou can combinate Chorus::Engine with Chorus::Frame which gives a first level
for knowledge representation. The inference engine can then work on Frames using the function 'fmatch'
top optimise the _SCOPE for the rules which work on frames.
SYNOPSIS
use Chorus::Engine;
my $agent = new Chorus::Engine();
$agent->addrule(
_SCOPE => { # These arrays will be combinated as parameters (HASH) when calling _APPLY
a => $subset, # static array_ref
b => sub { .. } # returns an array ref
},
_APPLY => sub {
my %opts = @_; # provides $opt{a},$opt{b} (~ one combinaison of _SCOPE)
if ( .. ) {
..
return 1; # rule could be applied (~ something has changed)
}
return undef; # rule didn't apply
}
);
$agent->loop();
SUBROUTINES/METHODS
addrule()
Defines a new rule for the Chorus::Engine object
arguments :
_SCOPE : a hashtable defining the variables and their search scope for instanciation
Values must be SCALAR or ARRAY_REF
_APPLY : function which will be called in a loop with all the possible
combinaisons from scopes on a & b
Ex. use Chorus::Engine;
use Chorus::Frames;
my $e=Chorus::Engine->new();
$e->addrule(
_SCOPE => {
foo => [ fmatch( .. ) ], # selection of Frames bases on the filter 'fmatch' (static)
bar => sub { [ fmatch( .. ) ] }, # same kind more dynamic
baz => [ .. ] # any other array (not only frames)
},
_APPLY => sub {
my %opts = @_; # provides $opt{foo},$opt{bar},$opt{baz}
return undef if ( .. ); # rule didn't apply
if ( .. ) {
.. # some actions
return 1; # rule could be applied
}
return undef; # rule didn't apply (last instruction)
});
loop()
Tells the Chorus::Engine object to enter its inference loop.
The loop will end only after all rules fail (~ return false) in the same iteration
Ex. my $agent = new Chorus::Engine();
$agent->addrule( .. );
..
$agent->addrule( .. );
$agent->loop();
cut()
Go directly to the next rule (same loop, same agent). This will break all nested instanciation loops
on _SCOPE of the current rule. -> GO DIRECTLY TO NEXT RULE (SAME AGENT)
Ex. $agent->addrule(
_SCOPE => { .. },
_APPLY => sub {
if ( .. ) {
$agent->cut(); # ~ exit the rule
}
);
last()
Breaks the current loop (on rules) for the current agent -> GO DIRECTLY TO NEXT AGENT
This will force a cut() too.
Ex. $agent->addrule(
_SCOPE => { .. },
_APPLY => sub {
if ( .. ) {
$agent->last();
}
);
replay()
Restart FROM THE BEGINNING (1st rule) for the CURRENT AGENT. This will force a cut() too.
Ex. $agent->addrule(
_SCOPE => { .. },
_APPLY => sub {
if ( .. ) {
$agent->replay();
}
);
replay_all()
Restart FROM THE BEGINNING for the FIRST AGENT. This will force a cut() too.
Ex. $agent->addrule(
_SCOPE => { .. },
_APPLY => sub {
if ( .. ) {
$agent->replay_all();
}
);
solved()
Tells the Chorus::Engine to terminate immediately. This will force a last() too
Ex. $agent->addrule(
_SCOPE => { .. },
_APPLY => sub {
if ( .. ) {
$agent->solved();
}
);
reorder()
the rules of the agent will be reordered according to the function given as argument (works like with sort()).
Note - The method last() will be automatically invoked.
Exemple : the current rule in a syntax analyser has found the category 'CAT_C' for a word.
The next step whould invoque as soon as possible the rules declared as interested
in this category.
sub sortA {
my ($r1, $r2) = @_;
return 1 if $r1->_INTEREST->CAT_C;
return -1 if $r2->_INTEREST->CAT_C;
return 0;
}
$agent->addrule( # rule 1
_INTEREST => { # user slot
CAT_C => 'Y',
# ..
},
_SCOPE => { .. }
_APPLY => sub { .. }
);
$agent->addrule( # rule n
_SCOPE => { .. }
_APPLY => sub {
# ..
if ( .. ) {
# ..
$agent->reorder(sortA); # will put rules interested in CAT_A to the head of the queue
}
}
);
pause()
Disable a Chorus::Engine object until call to wakeup(). In this mode, the method loop() has no effect.
This method can optimise the application by de-activating a Chorus::Engine object until it has
a good reason to work (ex. when a certain state is reached in the application ).
wakeup()
Enable a Chorus::Engine object -> will try again to apply its rules after next call to loop()
reorderRules()
use from rules body to optimize the engine defining best candidates (rules) for next loop (break the current loop)
applyrules()
main engine loop (iterates on $SELF->_RULES)
new contructor : initialize a new engine
AUTHOR
Christophe Ivorra, <ch.ivorra at free.fr>
BUGS
Please report any bugs or feature requests to bug-chorus-engine at rt.cpan.org
, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Chorus-Engine. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
SUPPORT
You can find documentation for this module with the perldoc command.
perldoc Chorus::Engine
You can also look for information at:
RT: CPAN's request tracker (report bugs here)
AnnoCPAN: Annotated CPAN documentation
CPAN Ratings
Search CPAN
ACKNOWLEDGEMENTS
LICENSE AND COPYRIGHT
Copyright 2013 Christophe Ivorra.
This program is free software; you can redistribute it and/or modify it under the terms of either: the GNU General Public License as published by the Free Software Foundation; or the Artistic License.
See http://dev.perl.org/licenses/ for more information.