AI-ExpertSystem-Simple

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

Revision history for Perl extension AI::ExpertSystem::Simple

1.0  Fri Apr 25 22:02:02 2003
	- original version; created by h2xs 1.20 with options
		-AX -n AI::ExpertSystem::Simple

Makefile.PL  view on Meta::CPAN

use strict;
use ExtUtils::MakeMaker;

WriteMakefile(
    NAME         => 'AI::ExpertSystem::Simple',
    VERSION_FROM => 'lib/AI/ExpertSystem/Simple.pm',
    EXE_FILES    => [
						'bin/simpleshell',
						'bin/consult'
					],
    PREREQ_PM    => {
        'XML::Twig' => 0,
    },
);

README  view on Meta::CPAN

So I dont have to write to a lowest common installation of PerlTk and
I don't have to explain in excruciating detail how to install PerlTk
on a variety of systems that I do not have access to. Suits me.

Also when I get to upgrade my Ruby version of this class it too can 
use the same shell. Go ahead and learn Tcl and Tk - it's rather 
usefull in it's own way.

INSTALLATION

 % perl Makefile.PL
 % make
 % make test
 % sudo make install

TEST FAILURES

The tests are there to make sure that I have broken nothing when I
fiddle with the code and will teach you very little about how to use
the code. 

To see how to use the code look at simpleshell in the bin directory
and read the contents of the docs directory (when I have written them).

bin/simpleshell  view on Meta::CPAN


my $s = AI::ExpertSystem::Simple->new();

$s->load($filename);

say_status("Consulting $filename");

my $continue = 'yes';

while($continue eq 'yes') {
	my $running = 1;

	while ($running) {
		my $r = $s->process();

		process_log();

		if ( $r eq 'question' ) {
			$s->answer( ask_question( $s->get_question() ) );
		}
		elsif ( $r eq 'finished' ) {
			say_status('The answer is : ' . $s->get_answer());
			$s->explain();
			process_log( 'explaination' , 1);
			$running = undef;
		}
		elsif ( $r eq 'failed' ) {
			say_status("Unable to answer your question");
			$running = undef;
		}
	}

	if($tkinterface) {
		$continue = 'no';
	} else {
		$continue = ask_question( 'Another consoltation', 'yes', 'no' );
		$s->reset();
	}
}

######################################################################
# Ask a question of the user showing the available responses
######################################################################

sub ask_question {
	my ( $text, @responses ) = @_;

	my $number = scalar(@responses);
	my $x      = 0;

	while ( $x < 1 or $x > $number ) {
		say_question($text);

		for ( my $y = 1 ; $y <= $number ; $y++ ) {
			say_something('response', " $y : ", $responses[$y - 1]);
		}

		if($tkinterface) {
			say_something('response', '', '*');
		} else { 
			print '** ';
		}
		$x = <STDIN>;

		$x = 0 if $x !~ m#^[0-9]+$#;
	}

	return $responses[ $x - 1 ];
}

######################################################################
# The various ways of printing out a message
######################################################################

sub say_status   { say_something('status',   '>> ', shift) }
sub say_question { say_something('question', '',    shift) }

sub say_something {
	my ($tag1, $tag2, $text) = @_;

	if($tkinterface) {
		print "$tag1:$text\n";
	} else {
		print "$tag2$text\n";
	}
}

######################################################################
# The various ways of printing out a message
######################################################################

sub process_log {
	my ($prefix, $override) = @_;

	$prefix = 'information' unless $prefix;

	my @log = $s->log();

	if($tkinterface or $override) {
		foreach my $line (@log) {
			say_something($prefix, '', $line);
		}
	}
}

examples/Animal.xml  view on Meta::CPAN

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE knowledgebase SYSTEM "sie-1.0.dtd">
<knowledgebase>
 <goal>
  <attribute>type.animal</attribute>
  <text>I think your animal is a type.animal</text>
 </goal>
 <rules>
  <rule>
   <name>1</name>
   <conditions>
    <condition>
     <attribute>backbone</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>superphylum</attribute>
     <value>backbone</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>2</name>
   <conditions>
    <condition>
     <attribute>backbone</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>superphylum</attribute>
     <value>jellyback</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>3</name>
   <conditions>
    <condition>
     <attribute>warm.blooded</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>superphylum</attribute>
     <value>backbone</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>phylum</attribute>
     <value>warm</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>4</name>
   <conditions>
    <condition>
     <attribute>warm.blooded</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>superphylum</attribute>
     <value>backbone</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>phylum</attribute>
     <value>cold</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>5</name>
   <conditions>
    <condition>
     <attribute>live.prime.in.soil</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>superphylum</attribute>
     <value>jellyback</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>phylum</attribute>
     <value>soil</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>6</name>
   <conditions>
    <condition>
     <attribute>live.prime.in.soil</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>superphylum</attribute>
     <value>jellyback</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>phylum</attribute>
     <value>elsewhere</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>7</name>
   <conditions>
    <condition>
     <attribute>has.breasts</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>phylum</attribute>
     <value>warm</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>class</attribute>
     <value>breasts</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>8</name>
   <conditions>
    <condition>
     <attribute>has.breasts</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>phylum</attribute>
     <value>warm</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>bird/penguin</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>9</name>
   <conditions>
    <condition>
     <attribute>always.in.water</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>phylum</attribute>
     <value>cold</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>class</attribute>
     <value>water</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>10</name>
   <conditions>
    <condition>
     <attribute>always.in.water</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>phylum</attribute>
     <value>cold</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>class</attribute>
     <value>dry</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>11</name>
   <conditions>
    <condition>
     <attribute>phylum</attribute>
     <value>soil</value>
    </condition>
    <condition>
     <attribute>flat.bodied</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>flatworm</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>12</name>
   <conditions>
    <condition>
     <attribute>phylum</attribute>
     <value>soil</value>
    </condition>
    <condition>
     <attribute>flat.bodied</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>worm/leech</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>13</name>
   <conditions>
    <condition>
     <attribute>phylum</attribute>
     <value>elsewhere</value>
    </condition>
    <condition>
     <attribute>body.in.segments</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>class</attribute>
     <value>segments</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>14</name>
   <conditions>
    <condition>
     <attribute>phylum</attribute>
     <value>elsewhere</value>
    </condition>
    <condition>
     <attribute>body.in.segments</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>class</attribute>
     <value>unified</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>15</name>
   <conditions>
    <condition>
     <attribute>can.eat.meat</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>class</attribute>
     <value>breasts</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>order</attribute>
     <value>meat</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>16</name>
   <conditions>
    <condition>
     <attribute>can.eat.meat</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>class</attribute>
     <value>breasts</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>order</attribute>
     <value>vegy</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>17</name>
   <conditions>
    <condition>
     <attribute>boney</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>class</attribute>
     <value>water</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>fish</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>18</name>
   <conditions>
    <condition>
     <attribute>boney</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>class</attribute>
     <value>water</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>shark/ray</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>19</name>
   <conditions>
    <condition>
     <attribute>class</attribute>
     <value>dry</value>
    </condition>
    <condition>
     <attribute>scally</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>order</attribute>
     <value>scales</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>20</name>
   <conditions>
    <condition>
     <attribute>class</attribute>
     <value>dry</value>
    </condition>
    <condition>
     <attribute>scally</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>order</attribute>
     <value>soft</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>21</name>
   <conditions>
    <condition>
     <attribute>class</attribute>
     <value>segments</value>
    </condition>
    <condition>
     <attribute>shell</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>order</attribute>
     <value>shell</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>22</name>
   <conditions>
    <condition>
     <attribute>class</attribute>
     <value>segments</value>
    </condition>
    <condition>
     <attribute>shell</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>centiped/milliped/insect</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>23</name>
   <conditions>
    <condition>
     <attribute>digest.cells</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>class</attribute>
     <value>unified</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>order</attribute>
     <value>cells</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>24</name>
   <conditions>
    <condition>
     <attribute>digest.cells</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>class</attribute>
     <value>unified</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>order</attribute>
     <value>stomach</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>25</name>
   <conditions>
    <condition>
     <attribute>fly</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>meat</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>bat</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>26</name>
   <conditions>
    <condition>
     <attribute>fly</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>meat</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>family</attribute>
     <value>nowings</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>27</name>
   <conditions>
    <condition>
     <attribute>hooves</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>vegy</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>family</attribute>
     <value>hooves</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>28</name>
   <conditions>
    <condition>
     <attribute>hooves</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>vegy</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>family</attribute>
     <value>feet</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>29</name>
   <conditions>
    <condition>
     <attribute>rounded.shell</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>scales</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>turtle</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>30</name>
   <conditions>
    <condition>
     <attribute>rounded.shell</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>scales</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>family</attribute>
     <value>noshell</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>31</name>
   <conditions>
    <condition>
     <attribute>jump</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>soft</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>frog</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>32</name>
   <conditions>
    <condition>
     <attribute>jump</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>soft</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>salamander</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>33</name>
   <conditions>
    <condition>
     <attribute>tail</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>shell</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>lobster</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>34</name>
   <conditions>
    <condition>
     <attribute>tail</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>shell</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>crab</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>35</name>
   <conditions>
    <condition>
     <attribute>stationary</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>cells</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>family</attribute>
     <value>stationary</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>36</name>
   <conditions>
    <condition>
     <attribute>stationary</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>cells</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>jellyfish</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>37</name>
   <conditions>
    <condition>
     <attribute>multicelled</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>stomach</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>family</attribute>
     <value>multicelled</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>38</name>
   <conditions>
    <condition>
     <attribute>multicelled</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>order</attribute>
     <value>stomach</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>protozoa</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>39</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>nowings</value>
    </condition>
    <condition>
     <attribute>opposing.thumb</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>genus</attribute>
     <value>thumb</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>40</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>nowings</value>
    </condition>
    <condition>
     <attribute>opposing.thumb</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>genus</attribute>
     <value>nothumb</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>41</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>hooves</value>
    </condition>
    <condition>
     <attribute>two.toes</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>genus</attribute>
     <value>twotoes</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>42</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>hooves</value>
    </condition>
    <condition>
     <attribute>two.toes</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>genus</attribute>
     <value>onetoe</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>43</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>feet</value>
    </condition>
    <condition>
     <attribute>live.in.water</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>genus</attribute>
     <value>water</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>44</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>feet</value>
    </condition>
    <condition>
     <attribute>live.in.water</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>genus</attribute>
     <value>dry</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>45</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>noshell</value>
    </condition>
    <condition>
     <attribute>limbs</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>crocodile/alligator</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>46</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>noshell</value>
    </condition>
    <condition>
     <attribute>limbs</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>snake</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>47</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>stationary</value>
    </condition>
    <condition>
     <attribute>spikes</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>sea.anemone</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>48</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>stationary</value>
    </condition>
    <condition>
     <attribute>spikes</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>coral/sponge</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>49</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>multicelled</value>
    </condition>
    <condition>
     <attribute>spiral.shell</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>snail</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>50</name>
   <conditions>
    <condition>
     <attribute>family</attribute>
     <value>multicelled</value>
    </condition>
    <condition>
     <attribute>spiral.shell</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>genus</attribute>
     <value>noshell</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>51</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>thumb</value>
    </condition>
    <condition>
     <attribute>prehensile.tail</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>monkey</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>52</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>thumb</value>
    </condition>
    <condition>
     <attribute>prehensile.tail</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>species</attribute>
     <value>notail</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>53</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>nothumb</value>
    </condition>
    <condition>
     <attribute>over.400</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>species</attribute>
     <value>400</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>54</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>nothumb</value>
    </condition>
    <condition>
     <attribute>over.400</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>species</attribute>
     <value>under400</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>55</name>
   <conditions>
    <condition>
     <attribute>horns</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>genus</attribute>
     <value>twotoes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>species</attribute>
     <value>horns</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>56</name>
   <conditions>
    <condition>
     <attribute>horns</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>genus</attribute>
     <value>twotoes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>species</attribute>
     <value>nohorns</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>57</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>onetoe</value>
    </condition>
    <condition>
     <attribute>plating</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>rhinoceros</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>58</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>onetoe</value>
    </condition>
    <condition>
     <attribute>plating</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>horse/zebra</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>59</name>
   <conditions>
    <condition>
     <attribute>hunted</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>genus</attribute>
     <value>water</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>whale</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>60</name>
   <conditions>
    <condition>
     <attribute>hunted</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>genus</attribute>
     <value>water</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>dolphin/porpoise</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>61</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>dry</value>
    </condition>
    <condition>
     <attribute>front.teeth</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>species</attribute>
     <value>teeth</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>62</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>dry</value>
    </condition>
    <condition>
     <attribute>front.teeth</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>species</attribute>
     <value>noteeth</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>63</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>noshell</value>
    </condition>
    <condition>
     <attribute>bivalve</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>clam/oyster</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>64</name>
   <conditions>
    <condition>
     <attribute>genus</attribute>
     <value>noshell</value>
    </condition>
    <condition>
     <attribute>bivalve</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>squid/octopus</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>65</name>
   <conditions>
    <condition>
     <attribute>nearly.hairless</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>notail</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>man</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>66</name>
   <conditions>
    <condition>
     <attribute>nearly.hairless</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>notail</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>subspecies</attribute>
     <value>hair</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>67</name>
   <conditions>
    <condition>
     <attribute>species</attribute>
     <value>400</value>
    </condition>
    <condition>
     <attribute>land.based</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>bear/tiger/lion</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>68</name>
   <conditions>
    <condition>
     <attribute>species</attribute>
     <value>400</value>
    </condition>
    <condition>
     <attribute>land.based</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>walrus</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>69</name>
   <conditions>
    <condition>
     <attribute>thintail</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>under400</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>cat</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>70</name>
   <conditions>
    <condition>
     <attribute>thintail</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>under400</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>coyote/wolf/fox/dog</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>71</name>
   <conditions>
    <condition>
     <attribute>one.horn</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>horns</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>hippopotamus</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>72</name>
   <conditions>
    <condition>
     <attribute>one.horn</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>horns</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>subspecies</attribute>
     <value>nohorn</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>73</name>
   <conditions>
    <condition>
     <attribute>lives.in.desert</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>nohorns</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>camel</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>74</name>
   <conditions>
    <condition>
     <attribute>lives.in.desert</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>nohorns</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>giraffe</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>75</name>
   <conditions>
    <condition>
     <attribute>large.ears</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>teeth</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>rabbit</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>76</name>
   <conditions>
    <condition>
     <attribute>large.ears</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>teeth</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>rat/mouse/squirrel/beaver/porcupine</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>77</name>
   <conditions>
    <condition>
     <attribute>pouch</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>noteeth</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>kangaroo/koala.bear</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>78</name>
   <conditions>
    <condition>
     <attribute>pouch</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>species</attribute>
     <value>noteeth</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>mole/shrew/elephant</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>79</name>
   <conditions>
    <condition>
     <attribute>long.powerful.arms</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>subspecies</attribute>
     <value>hair</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>orangutan/gorilla/chimpanzie</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>80</name>
   <conditions>
    <condition>
     <attribute>long.powerful.arms</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>subspecies</attribute>
     <value>hair</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>baboon</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>81</name>
   <conditions>
    <condition>
     <attribute>fleece</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>subspecies</attribute>
     <value>nohorn</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>sheep/goat</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>82</name>
   <conditions>
    <condition>
     <attribute>fleece</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>subspecies</attribute>
     <value>nohorn</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>subsubspecies</attribute>
     <value>nofleece</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>83</name>
   <conditions>
    <condition>
     <attribute>domesticated</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>subsubspecies</attribute>
     <value>nofleece</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>cow</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>84</name>
   <conditions>
    <condition>
     <attribute>domesticated</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>subsubspecies</attribute>
     <value>nofleece</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.animal</attribute>
     <value>deer/moose/antelope</value>
    </action>
   </actions>
  </rule>
 </rules>
 <questions>
  <question>
   <attribute>long.powerful.arms</attribute>
   <text>Does your animal have long, powerful arms?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>lives.in.desert</attribute>
   <text>Does your animal normally live in the desert?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>thintail</attribute>
   <text>Does your animal have a thin tail?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>bivalve</attribute>
   <text>Is your animal protected by two half-shells?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>hunted</attribute>
   <text>Is your animal, unfortunately, commercially hunted?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>jump</attribute>
   <text>Does your animal jump?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>hooves</attribute>
   <text>Does your animal have hooves?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>always.in.water</attribute>
   <text>Is your animal always in water?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>horns</attribute>
   <text>Does your animal have horns?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>two.toes</attribute>
   <text>Does your animal stand on two toes/hooves per foot?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>flat.bodied</attribute>
   <text>Does your animal have a flat body?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>live.prime.in.soil</attribute>
   <text>Does your animal live primarily in soil?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>domesticated</attribute>
   <text>Is your animal domesticated?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>pouch</attribute>
   <text>Does your animal have a pouch?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>over.400</attribute>
   <text>Does an adult normally weigh over 400 pounds?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>opposing.thumb</attribute>
   <text>Does your animal have an opposing thumb?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>can.eat.meat</attribute>
   <text>Does your animal eat red meat?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>warm.blooded</attribute>
   <text>Is the animal warm blooded?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>limbs</attribute>
   <text>Does your animal have limbs?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>body.in.segments</attribute>
   <text>Is the animals body in segments?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>has.breasts</attribute>
   <text>Normally, does the female of your animal nurse its young with milk?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>fleece</attribute>
   <text>Does your animal have fleece?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>nearly.hairless</attribute>
   <text>Is your animal nearly hairless?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>prehensile.tail</attribute>
   <text>Does your animal have a prehensile tail?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>rounded.shell</attribute>
   <text>Does the animal have a rounded shell?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>scally</attribute>
   <text>Is your animal covered with scaled skin?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>boney</attribute>
   <text>Does your animal have a boney skeleton?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>large.ears</attribute>
   <text>Does your animal have large ears?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>one.horn</attribute>
   <text>Does your animal have one horn?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>land.based</attribute>
   <text>Is your animal land based?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>plating</attribute>
   <text>Is your animal covered with a protective plating?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>tail</attribute>
   <text>Does your animal have a tail?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>backbone</attribute>
   <text>Does your animal have a backbone?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>front.teeth</attribute>
   <text>Does your animal have large front teeth?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>multicelled</attribute>
   <text>Is your animal made up of more than one cell?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>stationary</attribute>
   <text>Is your animal attached permanently to an object?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>fly</attribute>
   <text>Can your animal fly?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>spiral.shell</attribute>
   <text>Does your animal have a spiral-shaped shell?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>spikes</attribute>
   <text>Does your animal normally have spikes radiating from it's body?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>live.in.water</attribute>
   <text>Does your animal live in water?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>digest.cells</attribute>
   <text>Does your animal use many cells to digest it's food instead of a stomach?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>shell</attribute>
   <text>Does your animal have a shell?</text>
   <response>yes</response>
   <response>no</response>
  </question>
 </questions>
</knowledgebase>

examples/Doctor.xml  view on Meta::CPAN

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE knowledgebase SYSTEM "sie-1.0.dtd">
<knowledgebase>
 <goal>
  <attribute>type.disease</attribute>
  <text>Based on rudimentary knowledge, I believe the child has type.disease</text>
 </goal>
 <rules>
  <rule>
   <name>1</name>
   <conditions>
    <condition>
     <attribute>active.temp.over.101</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>fever</attribute>
     <value>yes</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>2</name>
   <conditions>
    <condition>
     <attribute>delayed.cough</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cold</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>whooping.cough</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>3</name>
   <conditions>
    <condition>
     <attribute>scratchy.throat</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>clear.nasal.discharge</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>cold</attribute>
     <value>yes</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>4</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cold</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>measle.rash</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>measles</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>5</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>squeaky.breath</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>vibration.chest</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>much.cough</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cold</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>bronchitis</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>6</name>
   <conditions>
    <condition>
     <attribute>wheezing</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cold</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>asthmatic.bronchitis</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>7</name>
   <conditions>
    <condition>
     <attribute>sinus.pain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cough.when.move</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>sinusitis</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>8</name>
   <conditions>
    <condition>
     <attribute>eczema</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>eczema</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>9</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>sputum</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cough</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>fatigue</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>tuberculosis</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>10</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>tender.joints</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>fatigue</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>rheumatic.fever</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>11</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>touch.to.chest</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>headache</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>anterior.poliomyelitis</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>12</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>sore.throat</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>scarlet.rash</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>vomiting</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>headache</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>scarlet.fever</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>13</name>
   <conditions>
    <condition>
     <attribute>tonsils.swollen</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>vomiting</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>headache</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>high.fever</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>tonsillitis</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>14</name>
   <conditions>
    <condition>
     <attribute>rapid.breathing</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cough</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>high.fever</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>pneumonia</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>15</name>
   <conditions>
    <condition>
     <attribute>high.fever</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>roseola</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>16</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>difficulty.breathing</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>hoarse.cough</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cold</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>severe.croup</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>17</name>
   <conditions>
    <condition>
     <attribute>difficulty.breathing</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>hoarse.cough</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>croup</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>18</name>
   <conditions>
    <condition>
     <attribute>impetigo.rash</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>impetigo</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>19</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>inflammed.ears</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>serious.ear.infection</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>20</name>
   <conditions>
    <condition>
     <attribute>inflammed.ears</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>ear.infection</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>21</name>
   <conditions>
    <condition>
     <attribute>hives.rash</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>itching</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>hives</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>22</name>
   <conditions>
    <condition>
     <attribute>ivy.rash</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>itching</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>poison.ivy</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>23</name>
   <conditions>
    <condition>
     <attribute>scabies.rash</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>itching</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>scabies</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>24</name>
   <conditions>
    <condition>
     <attribute>measle.rash</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>german.measles</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>25</name>
   <conditions>
    <condition>
     <attribute>naval.pain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>tender.abdomen</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>appendicitis</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>26</name>
   <conditions>
    <condition>
     <attribute>neck.swelling</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>mumps</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>27</name>
   <conditions>
    <condition>
     <attribute>nervous.disease</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>chorea</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>28</name>
   <conditions>
    <condition>
     <attribute>pox.rash</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>chicken.pox</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>29</name>
   <conditions>
    <condition>
     <attribute>prickly.rash</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>prickly.heat</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>30</name>
   <conditions>
    <condition>
     <attribute>rest.temp.over.100</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>fever</attribute>
     <value>yes</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>31</name>
   <conditions>
    <condition>
     <attribute>ringworm.rash</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>ringworm</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>32</name>
   <conditions>
    <condition>
     <attribute>sneeze</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>itchy.nose</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>allergy</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>33</name>
   <conditions>
    <condition>
     <attribute>fever</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>sore.throat</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>dirty.white.patches</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.disease</attribute>
     <value>diptheria</value>
    </action>
   </actions>
  </rule>
 </rules>
 <questions>
  <question>
   <attribute>squeaky.breath</attribute>
   <text>Does the child squeake as he breaths?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>itching</attribute>
   <text>Does the child complain of itchy or scratchy skin?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>high.fever</attribute>
   <text>Is the child's temperature over 103?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>fatigue</attribute>
   <text>Does the child complain of general fatigue?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>clear.nasal.discharge</attribute>
   <text>Does the child have a clear nasal discharge?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>tender.joints</attribute>
   <text>Does the child complain of tender joints?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>sputum</attribute>
   <text>Is the child producing sputum?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>sneeze</attribute>
   <text>Is the child sneezing?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>neck.swelling</attribute>
   <text>Does the child have extensive swelling in the side of his neck?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>ivy.rash</attribute>
   <text>Are there clusters of small blisters on reddened shiny skin?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>itchy.nose</attribute>
   <text>Does the child complain of an itchy nose?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>delayed.cough</attribute>
   <text>Did the child start coughing about one week after getting the cold?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>cough</attribute>
   <text>Does the child have a cough?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>impetigo.rash</attribute>
   <text>Are there pimples on the child with a partly brown crust?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>cough.when.move</attribute>
   <text>Does the child start coughing violently when he either lays down or gets up?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>vibration.chest</attribute>
   <text>Can you feel a vibration in the child's chest as he breaths?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>tender.abdomen</attribute>
   <text>Does the child have a tender abdomen on the right side?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>scratchy.throat</attribute>
   <text>Does the child have a scratchy throat?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>rapid.breathing</attribute>
   <text>Does the child have rapid, shallow breathing?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>vomiting</attribute>
   <text>Is the child vomiting?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>naval.pain</attribute>
   <text>Has the child complained of pain around his naval for several hours?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>inflammed.ears</attribute>
   <text>Does the child have inflammed ears?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>hoarse.cough</attribute>
   <text>Does the child have a hoarse cough?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>sinus.pain</attribute>
   <text>Does the child have any sinus pain?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>dirty.white.patches</attribute>
   <text>Does the child have dirty white patches on his tonsils?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>scarlet.rash</attribute>
   <text>Does the child have a red blush-like rash on his skin?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>scabies.rash</attribute>
   <text>Are there groups of pimples topped with scabs on the child?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>ringworm.rash</attribute>
   <text>Are there circular patches of rough skin on the child?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>prickly.rash</attribute>
   <text>Does the child have patches of tan-pink pimples?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>headache</attribute>
   <text>Does the child complain of headache?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>difficulty.breathing</attribute>
   <text>Does the child have difficulty breathing?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>active.temp.over.101</attribute>
   <text>Has the child been active in the last hour and his temp is greater than 101?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>wheezing</attribute>
   <text>Is the child wheezing?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>touch.to.chest</attribute>
   <text>Is it impossible for the child to touch his chin to his chest?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>tonsils.swollen</attribute>
   <text>Are the child's tonsils swollen with white patches on them?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>sore.throat</attribute>
   <text>Does the child have a sore throat?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>rest.temp.over.100</attribute>
   <text>Has the child been resting for over an hour and his temp is greater than 100?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>pox.rash</attribute>
   <text>Does the child's skin have separate, raised pimples, several with blisters?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>nervous.disease</attribute>
   <text>Does the child have twitching or writhing movements in DIFFERENT places?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>much.cough</attribute>
   <text>Does the child cough a lot, and cough syrup is roughly ineffective?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>measle.rash</attribute>
   <text>Does the child have flat pink spots on the skin?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>hives.rash</attribute>
   <text>Does the child have raised welts that are white in color?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>eczema</attribute>
   <text>Does the child have patches of rough, red, rash, scaly skin?</text>
   <response>yes</response>
   <response>no</response>
  </question>
 </questions>
</knowledgebase>

examples/Glass.xml  view on Meta::CPAN

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE knowledgebase SYSTEM "sie-1.0.dtd">
<knowledgebase>
 <goal>
  <attribute>type.glass</attribute>
  <text>The type of glass you have is type.glass</text>
 </goal>
 <rules>
  <rule>
   <name>1</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>pretzel</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>pretzel</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>2</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>square</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>block.optic</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>3</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>carribean</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>4</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>bead.block</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>beaded.block</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>5</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>bubble</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>bubble</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>6</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cube</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>cube</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>7</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>lace.edge</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>lace.edge</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>8</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>moonstone</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>moonstone</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>9</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>waterford</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>waterford</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>10</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>geometric</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>miss.america</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>11</name>
   <conditions>
    <condition>
     <attribute>avocado</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>avocado</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>12</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>cherry.blossom</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>cherry.blossom</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>13</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>fire.king</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>fire.king.oven.glass</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>14</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>sharon</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>sharon(cabbage.rose)</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>15</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>sunflower</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>sunflower</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>16</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>dogwood</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>17</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>alice</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>alice</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>18</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>iris</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>iris</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>19</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>mayfair</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>20</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>candlewick</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>candlewick</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>21</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>decagon</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>decagon</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>22</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>empress</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>empress</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>23</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>lariat</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>lariat</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>24</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>octagon</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>octagon</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>25</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>fairfax</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>26</name>
   <conditions>
    <condition>
     <attribute>ruby</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>royal.ruby</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>27</name>
   <conditions>
    <condition>
     <attribute>rays</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>plain</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>no</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>forest.green</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>28</name>
   <conditions>
    <condition>
     <attribute>fuchsia</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>emblem</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>fuchsia</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>29</name>
   <conditions>
    <condition>
     <attribute>emblem</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>large.rose</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>rose</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>30</name>
   <conditions>
    <condition>
     <attribute>orchid</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>emblem</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>orchid</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>31</name>
   <conditions>
    <condition>
     <attribute>emblem</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>pineapple</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>plantation</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>32</name>
   <conditions>
    <condition>
     <attribute>emblem</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>apple.blossom</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>33</name>
   <conditions>
    <condition>
     <attribute>emblem</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>cupid</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>cupid</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>34</name>
   <conditions>
    <condition>
     <attribute>rose.in.emblem</attribute>
     <value>no</value>
    </condition>
    <condition>
     <attribute>emblem</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>cherokee.rose</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>35</name>
   <conditions>
    <condition>
     <attribute>rose.in.emblem</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>emblem</attribute>
     <value>yes</value>
    </condition>
    <condition>
     <attribute>etched</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>type.glass</attribute>
     <value>rose.point</value>
    </action>
   </actions>
  </rule>
 </rules>
 <questions>
  <question>
   <attribute>lariat</attribute>
   <text>Does the piece have a looped rim?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>cherry.blossom</attribute>
   <text>Are there small cherries in the pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>pretzel</attribute>
   <text>Does the glass have a laced pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>moonstone</attribute>
   <text>Is the glass beaded with a white edge?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>fuchsia</attribute>
   <text>Are there Fuchsia, or hanging flowers with stems in them, in the glass?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>etched</attribute>
   <text>Is the glass etched? (versus pressed)</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>empress</attribute>
   <text>Does the rim look as though there are knotches?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>waterford</attribute>
   <text>Does the glass have a laced pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>rays</attribute>
   <text>Are there 'rays' starting in the center of the piece moving toward the edge?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>geometric</attribute>
   <text>Is there a geometric pattern in the glass?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>fire.king</attribute>
   <text>Are flowers missing from the pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>emblem</attribute>
   <text>Does the glass bear an emblem?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>plain</attribute>
   <text>Is the glass basically without a pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>octagon</attribute>
   <text>Is the glass eight sided?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>iris</attribute>
   <text>Does the glass have iris flowers?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>cupid</attribute>
   <text>Is there a cupid figure in the emblem?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>decagon</attribute>
   <text>Is the glass ten sided?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>candlewick</attribute>
   <text>Does the glass have balls around the rim?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>avocado</attribute>
   <text>Are there two avocado plants present (looks like two pears)?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>sunflower</attribute>
   <text>Are there sunflowers in the pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>pineapple</attribute>
   <text>Are there images of pineapples in the glass?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>orchid</attribute>
   <text>Are there orchids in the glass?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>lace.edge</attribute>
   <text>Does the piece have a flat rim with holes, giving a lacey apperance?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>alice</attribute>
   <text>Are there small flowers only around the rim of the piece?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>ruby</attribute>
   <text>Is the piece a deep ruby red in color?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>rose.in.emblem</attribute>
   <text>Is there a rose in the emblem?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>square</attribute>
   <text>Does the glass have a square pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>sharon</attribute>
   <text>Are there six 'spokes' in the piece?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>large.rose</attribute>
   <text>Are there large roses in the glass?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>cube</attribute>
   <text>Does the glass have a cubed pattern?</text>
   <response>yes</response>
   <response>no</response>
  </question>
  <question>
   <attribute>bead.block</attribute>
   <text>Does the glass have squares with beads connecting the squares?</text>
   <response>yes</response>
   <response>no</response>
  </question>
 </questions>
</knowledgebase>

examples/test.xml  view on Meta::CPAN

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE knowledgebase SYSTEM "sie-1.0.dtd">
<knowledgebase>
 <goal>
  <attribute>thegoal</attribute>
  <text>You have set the goal to thegoal</text>
 </goal>
 <rules>
  <rule>
   <name>1</name>
   <conditions>
    <condition>
     <attribute>one</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>thegoal</attribute>
     <value>pretzel</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>2</name>
   <conditions>
    <condition>
     <attribute>two</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>one</attribute>
     <value>yes</value>
    </action>
   </actions>
  </rule>
 </rules>
 <questions>
  <question>
   <attribute>two</attribute>
   <text>Answer yes to make this work</text>
   <response>yes</response>
   <response>no</response>
  </question>
 </questions>
</knowledgebase>

lib/AI/ExpertSystem/Simple.pm  view on Meta::CPAN


use XML::Twig;

use AI::ExpertSystem::Simple::Rule;
use AI::ExpertSystem::Simple::Knowledge;
use AI::ExpertSystem::Simple::Goal;

our $VERSION = '1.2';

sub new {
	my ($class) = @_;

	die "Simple->new() takes no arguments" if scalar(@_) != 1;

	my $self = {};

	$self->{_rules} = ();
	$self->{_knowledge} = ();
	$self->{_goal} = undef;
	$self->{_filename} = undef;

	$self->{_ask_about} = undef;
	$self->{_told_about} = undef;

	$self->{_log} = ();

	$self->{_number_of_rules} = 0;
	$self->{_number_of_attributes} = 0;
	$self->{_number_of_questions} = 0;

	return bless $self, $class;
}

sub reset {
	my ($self) = @_;

	die "Simple->reset() takes no arguments" if scalar(@_) != 1;

	foreach my $name (keys %{$self->{_rules}}) {
		$self->{_rules}->{$name}->reset();
	}

	foreach my $name (keys %{$self->{_knowledge}}) {
		$self->{_knowledge}->{$name}->reset();
	}

	$self->{_ask_about} = undef;
	$self->{_told_about} = undef;
	$self->{_log} = ();
}

sub load {
	my ($self, $filename) = @_;

	die "Simple->load() takes 1 argument" if scalar(@_) != 2;
	die "Simple->load() argument 1 (FILENAME) is undefined" if !defined($filename);

	if(-f $filename and -r $filename) {
		my $twig = XML::Twig->new(
			twig_handlers => { goal => sub { $self->_goal(@_) },
					   rule => sub { $self->_rule(@_) },
					   question => sub { $self->_question(@_) } }
		);

		$twig->safe_parsefile($filename);

		die "Simple->load() XML parse failed: $@" if $@;

		$self->{_filename} = $filename;

		$self->_add_to_log( "Read in $filename" );
		$self->_add_to_log( "There are " . $self->{_number_of_rules} . " rules" );
		$self->_add_to_log( "There are " . $self->{_number_of_attributes} . " attributes" );
		$self->_add_to_log( "There are " . $self->{_number_of_questions} . " questions" );
		$self->_add_to_log( "The goal attibutes is " . $self->{_goal}->name() );
		return 1;
	} else {
		die "Simple->load() unable to use file";
	}
}

sub _goal {
	my ($self, $t, $node) = @_;

	my $attribute = undef;
	my $text = undef;

	my $x = ($node->children('attribute'))[0];
	$attribute = $x->text();

	$x = ($node->children('text'))[0];
	$text = $x->text();

	$self->{_goal} = AI::ExpertSystem::Simple::Goal->new($attribute, $text);

	eval { $t->purge(); }
}

sub _rule {
	my ($self, $t, $node) = @_;

	my $name = undef;

	my $x = ($node->children('name'))[0];
	$name = $x->text();

	if(!defined($self->{_rules}->{$name})) {
		$self->{_rules}->{$name} = AI::ExpertSystem::Simple::Rule->new($name);
		$self->{_number_of_rules}++;
	}

	foreach $x ($node->get_xpath('//condition')) {
		my $attribute = undef;
		my $value = undef;

		my $y = ($x->children('attribute'))[0];
		$attribute = $y->text();

		$y = ($x->children('value'))[0];
		$value = $y->text();

		$self->{_rules}->{$name}->add_condition($attribute, $value);

		if(!defined($self->{_knowledge}->{$attribute})) {
			$self->{_number_of_attributes}++;
			$self->{_knowledge}->{$attribute} = AI::ExpertSystem::Simple::Knowledge->new($attribute);
		}
	}

	foreach $x ($node->get_xpath('//action')) {
		my $attribute = undef;
		my $value = undef;

		my $y = ($x->children('attribute'))[0];
		$attribute = $y->text();

		$y = ($x->children('value'))[0];
		$value = $y->text();

		$self->{_rules}->{$name}->add_action($attribute, $value);

		if(!defined($self->{_knowledge}->{$attribute})) {
			$self->{_number_of_attributes}++;
			$self->{_knowledge}->{$attribute} = AI::ExpertSystem::Simple::Knowledge->new($attribute);
		}
	}

	eval { $t->purge(); }
}

sub _question {
	my ($self, $t, $node) = @_;

	my $attribute = undef;
	my $text = undef;
	my @responses = ();

	$self->{_number_of_questions}++;

	my $x = ($node->children('attribute'))[0];
	$attribute = $x->text();

	$x = ($node->children('text'))[0];
	$text = $x->text();

	foreach $x ($node->children('response')) {
		push(@responses, $x->text());
	}

	if(!defined($self->{_knowledge}->{$attribute})) {
		$self->{_number_of_attributes}++;
		$self->{_knowledge}->{$attribute} = AI::ExpertSystem::Simple::Knowledge->new($attribute);
	}
	$self->{_knowledge}->{$attribute}->set_question($text, @responses);

	eval { $t->purge(); }
}

sub process {
	my ($self) = @_;

	die "Simple->process() takes no arguments" if scalar(@_) != 1;

	my $n = $self->{_goal}->name();

	if($self->{_knowledge}->{$n}->is_value_set()) {
		return 'finished';
	}

	if($self->{_ask_about}) {
		my %answers = ();

		$answers{$self->{_ask_about}}->{value} = $self->{_told_about};
		$answers{$self->{_ask_about}}->{setter} = '';

		$self->{_ask_about} = undef;
		$self->{_told_about} = undef;

		while(%answers) {
			my %old_answers = %answers;
			%answers = ();

			foreach my $answer (keys(%old_answers)) {
				my $n = $answer;
				my $v = $old_answers{$answer}->{value};
				my $s = $old_answers{$answer}->{setter};

				$self->_add_to_log( "Setting '$n' to '$v'" );

				$self->{_knowledge}->{$n}->set_value($v,$s);

				foreach my $key (keys(%{$self->{_rules}})) {
					if($self->{_rules}->{$key}->state() eq 'active') {
						my $state = $self->{_rules}->{$key}->given($n, $v);
						if($state eq 'completed') {
							$self->_add_to_log( "Rule '$key' has completed" );
							my %y = $self->{_rules}->{$key}->actions();
							foreach my $k (keys(%y)) {
								$self->_add_to_log( "Rule '$key' is setting '$k' to '$y{$k}'" );
								$answers{$k}->{value} = $y{$k};
								$answers{$k}->{setter} = $key;
							}
						} elsif($state eq 'invalid') {
							$self->_add_to_log( "Rule '$key' is now inactive" );
						}
					}
				}
			}
		}

		return 'continue';
	} else {
		my %scoreboard = ();

		foreach my $rule (keys(%{$self->{_rules}})) {
			if($self->{_rules}->{$rule}->state() eq 'active') {
				my @listofquestions = $self->{_rules}->{$rule}->unresolved();
				my $ok = 1;
				my @questionstoask = ();
				foreach my $name (@listofquestions) {
					if($self->{_knowledge}->{$name}->has_question()) {
						push(@questionstoask, $name);
					} else {
						$ok = 0;
					}
				}

				if($ok == 1) {
					foreach my $name (@questionstoask) {
						$scoreboard{$name}++;
					}
				}
			}
		}

		my $max_value = 0;

		foreach my $name (keys(%scoreboard)) {
			if($scoreboard{$name} > $max_value) {
				$max_value = $scoreboard{$name};
				$self->{_ask_about} = $name;
			}
		}

		return $self->{_ask_about} ? 'question' : 'failed';
	}
}

sub get_question {
	my ($self) = @_;

	die "Simple->get_question() takes no arguments" if scalar(@_) != 1;

	return $self->{_knowledge}->{$self->{_ask_about}}->get_question();
}

sub answer {
	my ($self, $value) = @_;

	die "Simple->answer() takes 1 argument" if scalar(@_) != 2;
	die "Simple->answer() argument 1 (VALUE) is undefined" if ! defined($value);

	$self->{_told_about} = $value;
}

sub get_answer {
	my ($self) = @_;

	die "Simple->get_answer() takes no arguments" if scalar(@_) != 1;

	my $n = $self->{_goal}->name();

	return $self->{_goal}->answer($self->{_knowledge}->{$n}->get_value());
}

sub log {
	my ($self) = @_;

	die "Simple->log() takes no arguments" if scalar(@_) != 1;

	my @return = ();
	@return = @{$self->{_log}} if defined @{$self->{_log}};

	$self->{_log} = ();

	return @return;
}

sub _add_to_log {
	my ($self, $message) = @_;

	push( @{$self->{_log}}, $message );
}

sub explain {
	my ($self) = @_;

	die "Simple->explain() takes no arguments" if scalar(@_) != 1;

	my $name  = $self->{_goal}->name();
	my $rule  = $self->{_knowledge}->{$name}->get_setter();
	my $value = $self->{_knowledge}->{$name}->get_value();

	my $x = "The goal '$name' was set to '$value' by " . ($rule ? "rule '$rule'" : 'asking a question' );
	$self->_add_to_log( $x );

	my @processed_rules;
	push( @processed_rules, $rule ) if $rule;

	$self->_explain_this( $rule, '', @processed_rules );
}

sub _explain_this {
	my ($self, $rule, $depth, @processed_rules) = @_;

	$self->_add_to_log( "${depth}Explaining rule '$rule'" );

	my %dont_do_these = map{ $_ => 1 } @processed_rules;

	my @check_these_rules = ();

	my %conditions = $self->{_rules}->{$rule}->conditions();
	foreach my $name (sort keys %conditions) {
		my $value = $conditions{$name};
		my $setter = $self->{_knowledge}->{$name}->get_setter();

		my $x = "$depth Condition '$name' was set to '$value' by " . ($setter ? "rule '$setter'" : 'asking a question' );
		$self->_add_to_log( $x );

		if($setter) {
			unless($dont_do_these{$setter}) {
				$dont_do_these{$setter} = 1;
				push( @check_these_rules, $setter );
			}
		}
	}

	my %actions = $self->{_rules}->{$rule}->actions();
	foreach my $name (sort keys %actions) {
		my $value = $actions{$name};

		my $x = "$depth Action set '$name' to '$value'";
		$self->_add_to_log( $x );
	}

	@processed_rules = keys %dont_do_these;

	foreach my $x ( @check_these_rules ) {
		push( @processed_rules, $self->_explain_this( $x, "$depth ", keys %dont_do_these ) );
	}

	return @processed_rules;
}

1;

=head1 NAME

AI::ExpertSystem::Simple - A simple expert system shell

=head1 VERSION

lib/AI/ExpertSystem/Simple/Goal.pm  view on Meta::CPAN

package AI::ExpertSystem::Simple::Goal;

use strict;
use warnings;

our $VERSION = '1.0';

sub new {
	my ($class, $name, $message) = @_;

	# Check the input

	die "Goal->new() takes 2 arguments" if scalar(@_) != 3;
	die "Goal->new() argument 1 (NAME) is undefined" if ! defined($name);
	die "Goal->new() argument 2 (MESSAGE) is undefined" if ! defined($message);

	# All OK, create the object

	my $self = {};

	$self->{_name} = $name;
	$self->{_message} = $message;

	return bless $self, $class;
}

sub is_goal {
	my ($self, $name) = @_;

	# Check the input

	die "Goal->is_goal() takes 1 argument" if scalar(@_) != 2;
	die "Goal->is_goal() argument 1 (NAME) is undefined" if ! defined($name);

	# All OK, do the stuff

	return $self->{_name} eq $name;
}

sub name {
	my ($self) = @_;

	# Check the input

	die "Goal->name() takes no arguments" if scalar(@_) != 1;

	# All OK, do the stuff

	return $self->{_name};
}

sub answer {
	my ($self, $value) = @_;

	# Check the input

	die "Goal->answer() takes 1 argument" if scalar(@_) != 2;
	die "Goal->answer() argument 1 (VALUE) is undefined" if ! defined($value);

	# All OK, do the stuff

	my @text = ();

	foreach my $word (split('\s', $self->{_message})) {
		if($word eq $self->{_name}) {
			push(@text, $value);
		} else {
			push(@text, $word);
		}
	}

	return join(' ', @text);
}

1;

=head1 NAME

AI::ExpertSystem::Simple::Goal - Utility class for a simple expert system

=head1 VERSION

lib/AI/ExpertSystem/Simple/Knowledge.pm  view on Meta::CPAN

package AI::ExpertSystem::Simple::Knowledge;

use strict;
use warnings;

our $VERSION = '1.2';

sub new {
	my ($class, $name) = @_;

    die "Knowledge->new() takes 1 argument" if scalar(@_) != 2;
    die "Knowledge->new() argument 1, (NAME) is undefined" if ! defined($name);

	my $self = {};

	$self->{_name} = $name;
	$self->{_value} = undef;
	$self->{_setter} = undef;
	$self->{_question} = undef;
	$self->{_responses} = ();

	return bless $self, $class;
}

sub reset {
	my ($self) = @_;

	die "Knowledge->reset() takes no arguments" if scalar(@_) != 1;

	$self->{_value} = undef;
	$self->{_setter} = undef;
}

sub set_value {
	my ($self, $value, $setter) = @_;

    die "Knowledge->set_value() takes 2 argument" if scalar(@_) != 3;
    die "Knowledge->set_value() argument 1, (VALUE) is undefined" if ! defined($value);
    die "Knowledge->set_value() argument 2, (SETTER) is undefined" if ! defined($setter);

	if(defined($self->{_value})) {
		die "Knowledge->set_value() has already been set";
	}

	$self->{_value} = $value;
	$self->{_setter} = $setter;
}

sub get_value {
	my ($self) = @_;

        die "Knowledge->get_value() takes no arguments" if scalar(@_) != 1;

	return $self->{_value};
}

sub get_setter {
	my ($self) = @_;

	die "Knowledge->get_setter() takes no arguments" if scalar(@_) != 1;

	return $self->{_setter};
}

sub is_value_set {
	my($self) = @_;

        die "Knowledge->is_value_set() takes no arguments" if scalar(@_) != 1;

	return defined($self->{_value});
}

sub set_question {
	my ($self, $question, @responses) = @_;

	if(defined($self->{_question})) {
		die "Knowledge->set_question() has already been set";
	}

        die "Knowledge->set_question() takes 2 arguments" if scalar(@_) < 3;
        die "Knowledge->set_question() argument 1, (QUESTION) is undefined" if ! defined($question);
#		This test just doesnt work for a list
#		die "Knowledge->set_question() argument 2, (RESPONSES) is undefined" if scalar(@responses) == 0;

	$self->{_question} = $question;
	push(@{$self->{_responses}}, @responses);
}

sub get_question {
	my ($self) = @_;

        die "Knowledge->get_question() takes no arguments" if scalar(@_) != 1;

	if(!defined($self->{_question})) {
		die "Knowledge->set_question() has not been set";
	}

	return ($self->{_question}, @{$self->{_responses}});
}

sub has_question {
	my ($self) = @_;

        die "Knowledge->has_question() takes no arguments" if scalar(@_) != 1;

	return (defined($self->{_question}) and !defined($self->{_value}));
}

sub name {
	my ($self) = @_;

        die "Knowledge->name() takes no arguments" if scalar(@_) != 1;

	return $self->{_name};
}

1;

=head1 NAME

AI::ExpertSystem::Simple::Knowledge - Utility class for a simple expert system

=head1 VERSION

lib/AI/ExpertSystem/Simple/Rule.pm  view on Meta::CPAN

package AI::ExpertSystem::Simple::Rule;

use strict;
use warnings;

our $VERSION = '1.2';

sub new {
	my ($class, $name) = @_;

	die "Rule->new() takes 1 argument" if(scalar(@_) != 2);
	die "Rule->new() argument 1 (NAME) is undefined" if(!defined($name));

	my $self = {};

	$self->{_name} = $name;
	$self->{_conditions} = ();
	$self->{_tested} = ();
	$self->{_counter} = 0;
	$self->{_actions} = ();
	$self->{_state} = 'active';

	return bless $self, $class;
}

sub reset {
	my ($self) = @_;

	# Check the input

	die "Rule->reset() takes no arguments" if scalar(@_) != 1;

	$self->{_state} = 'active';
	$self->{_counter} = 0;

	foreach my $name (keys %{$self->{_tested}}) {
		$self->{_tested}->{$name} = 0;
		$self->{_counter}++;
	}
}

sub add_condition {
	my ($self, $name, $value) = @_;

	die "Rule->add_condition() takes 2 arguments" if(scalar(@_) != 3);
	die "Rule->add_condition() argument 1 (NAME) is undefined" if(!defined($name));
	die "Rule->add_condition() argument 2 (VALUE) is undefined" if(!defined($value));

	if(defined($self->{_conditions}->{$name})) {
		die "Rule->add_condition() has already been set";
	}

	$self->{_conditions}->{$name} = $value;
	$self->{_tested}->{$name} = 0;
	$self->{_counter}++;
}

sub add_action {
	my ($self, $name, $value) = @_;

	die "Rule->add_action() takes 2 arguments" if(scalar(@_) != 3);
	die "Rule->add_action() argument 1 (NAME) is undefined" if(!defined($name));
	die "Rule->add_action() argument 2 (VALUE) is undefined" if(!defined($value));

	if(defined($self->{_actions}->{$name})) {
		die "Rule->add_action() has already been set";
	}

	$self->{_actions}->{$name} = $value;
}

sub name {
	my ($self) = @_;

	die "Rule->name() takes no arguments" if(scalar(@_) != 1);

	return $self->{_name};
}

sub state {
	my ($self) = @_;

	die "Rule->state() takes no arguments" if(scalar(@_) != 1);

	return $self->{_state};
}

sub given {
	my ($self, $name, $value) = @_;

	die "Rule->given() takes 2 arguments" if(scalar(@_) != 3);
	die "Rule->given() argument 1 (NAME) is undefined" if(!defined($name));
	die "Rule->given() argument 2 (VALUE) is undefined" if(!defined($value));

	if(defined($self->{_conditions}->{$name})) {
		if($self->{_tested}->{$name} == 1) {
			# Already done this one
		} elsif($self->{_conditions}->{$name} eq $value) {
			$self->{_tested}->{$name} = 1;
			$self->{_counter}--;
			if($self->{_counter} == 0) {
				$self->{_state} = 'completed';
			}
		} else {
			$self->{_state} = 'invalid';
		}
	}

	return $self->{_state};
}

sub actions {
	my ($self) = @_;

	die "Rule->actions() takes no arguments" if(scalar(@_) != 1);

	return %{$self->{_actions}};
}

sub conditions {
	my ($self) = @_;

	die "Rule->conditions() takes no arguments" if(scalar(@_) != 1);

	return %{$self->{_conditions}};
}

sub unresolved {
	my ($self) = @_;

	die "Rule->unresolved() takes no arguments" if(scalar(@_) != 1);

	my @list = ();

	foreach my $name (keys(%{$self->{_tested}})) {
		if($self->{_tested}->{$name} == 0) {
			push(@list, $name);
		}
	}

	return @list;
}

1;

=head1 NAME

AI::ExpertSystem::Simple::Rule - A utility class for a simple expert system

=head1 VERSION

t/test.xml  view on Meta::CPAN

<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE knowledgebase SYSTEM "sie-1.0.dtd">
<knowledgebase>
 <goal>
  <attribute>thegoal</attribute>
  <text>You have set the goal to thegoal</text>
 </goal>
 <rules>
  <rule>
   <name>1</name>
   <conditions>
    <condition>
     <attribute>one</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>thegoal</attribute>
     <value>pretzel</value>
    </action>
   </actions>
  </rule>
  <rule>
   <name>2</name>
   <conditions>
    <condition>
     <attribute>two</attribute>
     <value>yes</value>
    </condition>
   </conditions>
   <actions>
    <action>
     <attribute>one</attribute>
     <value>yes</value>
    </action>
   </actions>
  </rule>
 </rules>
 <questions>
  <question>
   <attribute>two</attribute>
   <text>Answer yes to make this work</text>
   <response>yes</response>
   <response>no</response>
  </question>
 </questions>
</knowledgebase>

 view all matches for this distribution
 view release on metacpan -  search on metacpan

( run in 0.930 second using v1.00-cache-2.02-grep-82fe00e-cpan-2c419f77a38b )