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).

README  view on Meta::CPAN

Peter Hickman <peterhi@ntlworld.com>

Copyright (c) 2003, Peter Hickman. All rights reserved.

This module is free software. It may be used, redistributed and/or 
modified under the same terms as Perl itself.

CHANGES IN THIS RELEASE

V1.02:
      - The explain method now works

V1.01:
      - Implemented the reset method
	  - Simpleshell now works with the consult the Tcl/Tk shell
	  - Included a copy of the Tcl/Tk shell

V1.00:
      - First release to CPAN

bin/consult  view on Meta::CPAN

set choice ""

toplevel .askme
wm withdraw .askme

################################################################################
# The question asking dialog
################################################################################

proc ask_the_user {message argv} {
	# Restore the toplevel item so that we can 
	# put the dialog box together

	wm deiconify .askme
	wm title .askme "What I want to know is?"

	# Set the question text

	label .askme.l -text $message -padx 10 -pady 10 -wraplength 300
	pack .askme.l -side top -anchor n

	# The is where the users choice will go
	global choice
	set choice ""

	# Set up each button
	set counter 1
	foreach option $argv {
		button .askme.$counter -text $option -command [list set choice $counter]
		pack .askme.$counter -side top -anchor n -fill x
		incr counter
	}

	vwait choice

	# Our option has been set, now dismantel the 
	# contents of the toplevel so we can build it
	# up again from scratch next time.

	wm withdraw .askme
	destroy .askme.l
	set counter 1
	foreach option $argv {
		destroy .askme.$counter
		incr counter
	}

	return $choice
}

################################################################################
# Setting up the window
################################################################################

proc main {} {
	wm title . "Simple Inference Engine"
	wm geometry . 500x500

	# The top frame holds the buttons

	frame .top
	button .load -text "Load..." -command "do_load" -width 8 
	button .run  -text "Run"     -command "do_run"  -width 8 -state disabled
	button .save -text "Save..." -command "do_save" -width 8 -state disabled
	checkbutton .display -text "Display 'information' messages" -variable display_information -onvalue 1 -offvalue 0
	pack .load .run .save .display -side left -anchor n -in .top
	pack .top -anchor nw

	# A log of the output is written here

	text .text -yscrollcommand {.textscroll set}
	scrollbar .textscroll -orient vertical -command {.text yview}
	pack .text -side top -anchor w -fill both -expand 1 
	pack .textscroll -side right -fill y -in .text

	# Define some colours

	.text tag config is_status      -foreground blue
	.text tag config is_question    -foreground red
	.text tag config is_response    -foreground cyan
	.text tag config is_answer      -foreground green
	.text tag config is_information -foreground grey

	# A nice hello message

	status "Welcome to the Tcl/Tk expert system shell"
	status ""
	status "This program is used to call the command line"
	status "expert system called simpleshell and allows"
	status "you to interact with it via the gui"
	status ""
	status "First select a knowledgebase to load with the Load button"
	status "Then start a consultation with the Run button"
	status "You can rerun the consultation as many times as you like"
	status ""
	status "The Save button allows you to save the contents of the"
	status "session to a file"
	status ""
	status "The \"Display 'information' messages\" check box is used"
	status "to turn the grey information messages on and off. The "
	status "information messages tell you what the expert system is"
	status "up to and can be quite voluminous"
	status ""
	status "Have fun - Peter Hickman"
	status ""

	# Do we have a command line file

	global filename
	if {$filename != ""} {
		load_a_file $filename
	}
}

################################################################################
# Code to handle the buttons
################################################################################

proc do_load {} {
	status "Load a file..."

	set types {{{XML Files} {.xml}} {{All Files} *}}

	global filename
	set filename [tk_getOpenFile -filetypes $types -title "Load a knowledge base"]

	if {$filename != ""} {
		load_a_file $filename
	} {
		status "No file was selected"
	}
}

proc load_a_file {filename} {
	if {[file isfile $filename] == 0} {
		status "The file you selected is not really a file"
	} elseif {[file readable $filename] == 0} {
		status "The file you selected in not readable"
	} else {
		.run  configure -state normal
		status "Loading file $filename"
		status "The next step is to Run it..."

		wm title . [append newtitle "Simple Inference Engine: " [file tail $filename]]
	}
}

proc do_run {} {
	status "Run the file..."
	status "This may take a few moments to get started..."
	.save configure -state normal
	.run  configure -state disabled

	global filename
	global program
	set filehandle [open "|$program -t $filename" "r+"]

	set question ''
	set responses [list]

	.text delete 0.1 end

	while {![eof $filehandle]} {
		set text [gets $filehandle]

		if {[regexp {^status:(.*)} $text match newtext]} {
			status $newtext
		} elseif {[regexp {^question:(.*)} $text match newtext]} {
			set question $newtext
			set responses [list]
			question $newtext
		} elseif {[regexp {^response:(.*)} $text match newtext]} {
			if {$newtext != "*"} {
				lappend responses "$newtext"
				response "One possible answer is => $newtext"
			} else {
				set is [ask_the_user $question $responses]
				puts $filehandle $is
				flush $filehandle
				incr is -1
				set word [lindex $responses $is]
				answer "Your answer is => $word"
			}
		} elseif {[regexp {^information:(.*)} $text match newtext]} {
			information $newtext
		} elseif {[regexp {^explaination:(.*)} $text match newtext]} {
			status $newtext
		} else {
			status $text
		}
	}

	.run  configure -state normal
}

proc do_save {} {
	status "Save the output..."

	set types { {{Text Files} {.txt} } {{All Files} * } }

	set filename [tk_getSaveFile -filetypes $types -title "Save the results of a run" -initialfile "Results.txt"]

	if {$filename != ""} {
		if {[file isfile $filename] == 0} {
			status "The file you selected is not really a file"
		} elseif {[file writeable $filename] == 0} {
			status "The file you selected in not writeable"
		} else {
			status "Saving the output to $filename"
			set handle [open $filename "w"]
			puts $handle [.text get 0.1 end]
			close $handle
		}
	} {
		status "No file was selected"
	}
}

################################################################################
# Utility functions
################################################################################

proc status      {text} { mymessage $text is_status }
proc question    {text} { mymessage $text is_question }
proc response    {text} { mymessage $text is_response }
proc answer      {text} { mymessage $text is_answer }

proc information {text} {
	global display_information
	if {$display_information == 1} {
		mymessage $text is_information
	}
}

proc mymessage {text tag} {
	.text insert end "$text\n" $tag
	.text see end
	update
}

################################################################################
# The program starts here
################################################################################

# Was there a filename on the command line

set p_count 0

while {[set err [cmdline::getopt argv {f.arg p.arg} opt val]] > 0} {
	switch -- $opt {
		f {
			if {$filename == ""} {
				set filename $val
			} {
				set error "The $opt switch should only be used once"
			}
		}
		p {
			if {$p_count == 0} {
				set program $val
				incr p_count
				if {[file executable $program] != 1} {
					set error "The program '$program' is not runable"
				}
			} {
				set error "The $opt switch should only be used once"
			}
		}
	}
}

if {$err < 0} {
	puts "There was an error: $val"
	exit
}\
elseif {$error != ""} {
	puts "There was an error: $error"
	exit
}

main

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>



( run in 0.399 second using v1.01-cache-2.11-cpan-4d50c553e7e )