AI-ExpertSystem-Advanced
view release on metacpan or search on metacpan
verbose
my $ai = AI::ExpertSystem::Advanced->new(
viewer_class => 'terminal',
knowledge_db => $yaml_kdb,
initial_facts => ['I'],
verbose => 1);
By default this is turned off. If you want to know what happens
behind the scenes turn this on.
Everything that needs to be debugged will be passed to the debug()
method of your viewer.
viewer
Is the object AI::ExpertSystem::Advanced will be using for printing
what is happening and for interacting with the user (such as asking
the asked_facts).
This is practical if you want to use a viewer object that is not
provided by AI::ExpertSystem::Advanced::Viewer::Factory.
lib/AI/ExpertSystem/Advanced.pm view on Meta::CPAN
my $ai = AI::ExpertSystem::Advanced->new(
viewer_class => 'terminal',
knowledge_db => $yaml_kdb,
initial_facts => ['I'],
verbose => 1);
By default this is turned off. If you want to know what happens behind the
scenes turn this on.
Everything that needs to be debugged will be passed to the L<debug()> method
of your L<viewer>.
=cut
has 'verbose' => (
is => 'rw',
isa => 'Bool',
default => 0);
=item B<viewer>
lib/AI/ExpertSystem/Advanced.pm view on Meta::CPAN
confess "Can't do forward algorithm with no initial facts" unless
$self->{'initial_facts_dict'};
my ($more_rules, $current_rule) = (1, undef);
while($more_rules) {
$current_rule = $self->{'knowledge_db'}->get_next_rule($current_rule);
# No more rules?
if (!defined $current_rule) {
$self->{'viewer'}->debug("We are done with all the rules, bye")
if $self->{'verbose'};
$more_rules = 0;
last;
}
$self->{'viewer'}->debug("Checking rule: $current_rule") if
$self->{'verbose'};
if ($self->is_rule_shot($current_rule)) {
$self->{'viewer'}->debug("We already shot rule: $current_rule")
if $self->{'verbose'};
next;
}
$self->{'viewer'}->debug("Reading rule $current_rule")
if $self->{'verbose'};
$self->{'viewer'}->debug("More rules to check, checking...")
if $self->{'verbose'};
my $rule_causes = $self->get_causes_by_rule($current_rule);
# any of our rule facts match with our facts to check?
if ($self->compare_causes_with_facts($current_rule)) {
# shoot and start again
$self->shoot($current_rule, 'forward');
# Undef to start reading from the first rule.
$current_rule = undef;
next;
lib/AI/ExpertSystem/Advanced.pm view on Meta::CPAN
my ($self) = @_;
my ($more_goals, $current_goal, $total_goals) = (
1,
0,
scalar(@{$self->{'goals_to_check'}}));
WAIT_FOR_MORE_GOALS: while($more_goals) {
READ_GOAL: while(my $goal = $self->{'goals_to_check_dict'}->iterate) {
if ($self->is_goal_in_our_facts($goal)) {
$self->{'viewer'}->debug("The goal $goal is in our facts")
if $self->{'debug'};
# Matches with any visiited rule?
my $rule_no = $self->{'goals_to_check_dict'}->get_value(
$goal, 'rule');
# Take out this goal so we don't end with an infinite loop
$self->{'viwer'}->debug("Removing $goal from goals to check")
if $self->{'debug'};
$self->{'goals_to_check_dict'}->remove($goal);
# Update the iterator
$self->{'goals_to_check_dict'}->populate_iterable_array();
# no more goals, what about rules?
if ($self->{'visited_rules'}->size() eq 0) {
$self->{'viewer'}->debug("No more goals to read")
if $self->{'verbose'};
$more_goals = 0;
next WAIT_FOR_MORE_GOALS;
}
if (defined $rule_no) {
my $causes_total = $self->{'visited_rules'}->get_value(
$rule_no, 'causes_total');
my $causes_pending = $self->{'visited_rules'}->get_value(
$rule_no, 'causes_pending');
if (defined $causes_total and defined $causes_pending) {
# No more pending causes for this rule, lets shoot it
if ($causes_pending-1 le 0) {
my $last_rule = $self->remove_last_visited_rule();
if ($last_rule eq $rule_no) {
$self->{'viewer'}->debug("Going to shoot $last_rule")
if $self->{'debug'};
$self->shoot($last_rule, 'backward');
} else {
$self->{'viewer'}->print_error(
"Seems the rule ($rule_no) of goal " .
"$goal is not the same as the last " .
"visited rule ($last_rule)");
$more_goals = 0;
next WAIT_FOR_MORE_GOALS;
}
} else {
lib/AI/ExpertSystem/Advanced.pm view on Meta::CPAN
} else {
$more_goals = 1;
}
# Re verify if there are more goals to check
next WAIT_FOR_MORE_GOALS;
} else {
# Ugh, the fact is not in our inference facts or asked facts,
# well, lets find the rule where this fact belongs
my $rule_of_goal = $self->get_rule_by_goal($goal);
if (defined $rule_of_goal) {
$self->{'viewer'}->debug("Found a rule with $goal as a goal")
if $self->{'debug'};
# Causes of this rule
my $rule_causes = $self->get_causes_by_rule($rule_of_goal);
# Copy the causes of this rule to our goals to check
$self->copy_to_goals_to_check($rule_of_goal, $rule_causes);
# We just *visited* this rule, lets check it
$self->visit_rule($rule_of_goal, $rule_causes->size());
# and yes.. we have more goals to check!
$self->{'goals_to_check_dict'}->populate_iterable_array();
$more_goals = 1;
next WAIT_FOR_MORE_GOALS;
lib/AI/ExpertSystem/Advanced.pm view on Meta::CPAN
if (
$answer eq FACT_SIGN_POSITIVE or
$answer eq FACT_SIGN_NEGATIVE) {
$self->{'asked_facts'}->append($goal,
{
name => $goal,
sign => $answer,
algorithm => 'backward'
});
} else {
$self->{'viewer'}->debug(
"Don't know of $goal, nothing else to check"
);
return 0;
}
$self->{'goals_to_check_dict'}->populate_iterable_array();
$more_goals = 1;
next WAIT_FOR_MORE_GOALS;
}
}
}
lib/AI/ExpertSystem/Advanced.pm view on Meta::CPAN
}
use Data::Dumper;
while(1) {
# We are satisfied if only one inference fact is positive (eg, means we
# got to our result)
while(my $fact = $self->{'inference_facts'}->iterate) {
my $sign = $self->{'inference_facts'}->get_value($fact, 'sign');
if ($sign eq FACT_SIGN_POSITIVE) {
$self->{'viewer'}->debug(
"We are done, a positive fact was found"
);
return 1;
}
}
my $intuitive_facts = AI::ExpertSystem::Advanced::Dictionary->new(
stack => []);
my ($more_rules, $current_rule) = (1, undef);
while($more_rules) {
$current_rule = $self->{'knowledge_db'}->get_next_rule($current_rule);
# No more rules?
if (!defined $current_rule) {
$self->{'viewer'}->debug("We are done with all the rules, bye")
if $self->{'verbose'};
$more_rules = 0;
last;
}
# Wait, we already shot this rule?
if ($self->is_rule_shot($current_rule)) {
$self->{'viewer'}->debug("We already shot rule: $current_rule")
if $self->{'verbose'};
next;
}
my $factor = $self->get_causes_match_factor($current_rule);
if ($factor ge $self->{'found_factor'} && $factor lt 1.0) {
# Copy all of the goals (usually only one) of the current rule to
# the intuitive facts
my $goals = $self->get_goals_by_rule($current_rule);
while(my $goal = $goals->iterate_reverse) {
$intuitive_facts->append($goal,
{
name => $goal,
sign => $goals->get_value($goal, 'sign')
});
}
}
}
if ($intuitive_facts->size() eq 0) {
$self->{'viewer'}->debug("Done with intuition") if
$self->{'verbose'};
return 1;
}
$intuitive_facts->populate_iterable_array();
# now each intuitive fact will be a goal
while(my $fact = $intuitive_facts->iterate) {
$self->{'goals_to_check_dict'}->append(
$fact,
{
name => $fact,
sign => $intuitive_facts->get_value($fact, 'sign')
});
$self->{'goals_to_check_dict'}->populate_iterable_array();
print "Running backward for $fact\n";
if (!$self->backward()) {
$self->{'viewer'}->debug("Backward exited");
return 1;
}
# Now we have inference facts, anything positive?
$self->{'inference_facts'}->populate_iterable_array();
while(my $inference_fact = $self->{'inference_facts'}->iterate) {
my $sign = $self->{'inference_facts'}->get_value(
$inference_fact, 'sign');
if ($sign eq FACT_SIGN_POSITIVE) {
$self->{'viewer'}->print(
"Done, a positive inference fact found"
lib/AI/ExpertSystem/Advanced/Viewer/Base.pm view on Meta::CPAN
context cause otherwise L<AI::ExpertSystem::Advanced> will die.
=cut
use Moose;
our $VERSION = '0.02';
use constant NO_ABSTRACT_CLASS_MSG =>
qq#Sorry, you can't call the abstract class!#;
=head2 B<debug($msg)>
Will be used to debug any task done by L<AI::ExpertSystem::Advanced>. It only
receives one parameter that is the message to print.
=cut
sub debug {
confess NO_ABSTRACT_CLASS_MSG;
}
=head2 B<print($msg)>
Will be used to print anything that is not a debug messages. It only receives
one parameter that is the message to print.
=cut
sub print {
confess NO_ABSTRACT_CLASS_MSG;
}
=head2 B<print_error($msg)>
Will be used to print any error of L<AI::ExpertSystem::Advanced>. It only
lib/AI/ExpertSystem/Advanced/Viewer/Terminal.pm view on Meta::CPAN
=back
=cut
has 'readline' => (
is => 'ro',
isa => 'Term::ReadLine');
=head1 Methods
=head2 B<debug($msg)>
Basically just prints the given C<$msg> but prepends the "DEBUG" string to it.
=cut
sub debug {
my ($self, $msg) = @_;
print "DEBUG: $msg\n";
}
=head2 B<print($msg)>
Simply prints the given C<$msg>.
=cut
sub print {
( run in 1.021 second using v1.01-cache-2.11-cpan-49f99fa48dc )