Source Code: Teacher's Timetable
TEACHERS.KSL Listing
/*
Timetable Example - Phil Vasey and Alan Westwood february 1999
==============================================================
Updated for WebFlex - May 2002 Clive Spenser and Alan Westwood
This example shows both forward and backward-chaining methods for
creating a timetable, though only forwards is made available over the web.
Description
-----------
Timetabling is a classical AI problem which involves both search and
strategy components. It has similar charactersistics to resource
allocation, scheduling and planning in general.
Running The Example
-------------------
The timetable example is presented as a choice between two contrasting
forward and backward chaining solutions. To run the example enter the
following goal at the command line:
?- run.
In this example we have some data that represents a number of
teachers, classes, subjects and periods. The teachers can teach
certain subjects and classes and have periods of freetime where they
are unavailable to teach.
Given this data, the basic requirement is to schedule a daily teaching
rota such that:
i. A teacher can only teach one class during a given period.
ii. A class is taught a subject once only per day.
You are encouraged to add a teacher or two to try and complete the rota.
This example compares two contrasting methods for implementing a
timetable given the above constraints. Both methods attempt to fill
the timetable as much as possible by suggesting teachers that can
teach a subject to a given class during a given period. This often
leads to a situation where there is a partially filled timetable,
where no more teachers and subjects can be given for the remaining
classes and periods without conflicts arising.
The two methods differ in how they deal with this deadlock.
Forward-chaining
----------------
This is the most efficient method, though there is no guarantee that
a potentially existing solution will always be found.
In this approach conflicts are resolved by either swapping previously
assigned teachers or previously assigned subjects. In this way
conflicts are resolved directly when they arise.
Backward-chaining
-----------------
This is less efficient than forward-chaining but if a solution exists
then this approach will eventually get there.
This methis is not made available over the web, but the code is here.
In this approach conflicts are resolved by blindly undoing the last
teacher and subject allocated, replacing them with some alternative,
and then attempting to fill out the rest of the timetable.
If this new allocation does not lead to a solution then this process
is repeated until all teacher - subject combinations have been
exhausted.
One problem with this method is that the very first teacher, class,
subject and period allocated may prevent a solution from being found,
yet this method will try all the possible solutions based on this
first allocation before rejecting it and trying an alternative.
Flex Technical Points
---------------------
The following flex technical points are demonstrated in this example:
1. The use of remember and forget to store values. It is important to
note that remembered facts are automatically forgotten on
backtracking.
2. The use of backward chaining relations in the forward chaining
process.
*/
% The first template outlines the following types of phrase:
% e.g. class alpha is taught maths by john during period 1
% class gamma is not taught french by mary during period 2
template taught
class ^ is taught ^ by ^ during period ^ ;
class ^ is not taught ^ by ^ during period ^ .
template not_yet_timetabled
class ^ needs timetabling for period ^ .
template potential_teacher
^ can potentially teach ^ to class ^ during period ^ .
template definite_teacher
^ can definitely teach ^ to class ^ during period ^ .
template bad_teacher
^ already teaches class ^ during ^ so cannot teach class ^ ;
^ does not teach any ^ during ^ so is available to teach class ^ .
template bad_subject
^ is already taught to ^ during ^ which conflicts with period ^ ;
^ is not taught to ^ at any other ^ so is available for period ^ .
action run ;
do restart
and new_teachers
and forward_chaining_timetable .
action show_teachers
do write( '<p>These are the teachers I know about: <//p>' )
and write( '<table border="1", cellpadding="8">' )
and write( '<th>Teacher<//th>' )
and write( '<th>Freetime<//th>' )
and write( '<th>Subjects<//th>' )
and write( '<th>Classes<//th>' )
and for every T is some instance of teacher
do write( '<tr>' )
and write_out( {{T},T`s freetime, T`s subjects, T`s classes } )
and write( '<//tr>' )
end for
and write( '<//table>' )
and write( '<//p>' ) .
action write_out( Set )
do for every member( X, Set )
do write_set( X )
end for .
action write_set( Set )
do write( '<td>' )
and for every member( Item, Set )
do write( Item ) and tab(1)
end for
and write( '<//td>' ) .
relation new_teachers
if show_teachers
and ask teacher_questions
and new_teacher_q is a new teacher whose subjects is subjects_q
and whose freetime is { freetime_q }
and whose classes is classes_q
and continue_q is yes
and !
and new_teachers .
relation new_teachers .
group teacher_questions
new_teacher_q, classes_q, subjects_q, freetime_q, continue_q .
frame teacher_questions_style
default caption is 'New Teacher' and
default columns is 2 and
default tablestyle is { bgcolor-'#ffffcc', cellpadding-4 } .
% First we set up the data for the timetable
% the following groups define the classes and periods
group class
class1, class2, class3, class4 .
group period
'1', '2', '3', '4', '5' .
group subjects
maths, physics, chemistry, english, geography, history .
% the following frame hierarchy defines the teachers, their subjects
% which classes they may teach and their freetime
frame teacher ;
default freetime is nothing and
default classes are every class .
instance john is a teacher ;
subjects are { maths and physics } and
freetime is { 3 } and
classes are { class1 and class2 }.
instance mary is a teacher ;
subjects are { french and maths } and
freetime is { 4 } and
classes are { class1 and class3 } .
instance matthew is a teacher ;
subjects are { history and geography } and
freetime is { 1 } and
classes are { class2 and class3 }.
instance helen is a teacher ;
subjects are { chemistry and physics } and
freetime is { 5 } and
classes are { class2 and class4 }.
instance henry is a teacher ;
subjects are { english and french } and
freetime is { 2 } and
classes are { class2 and class4 }.
question continue_q
Any more teachers to enter? ;
choose one of yes, no
because if there are no more new teachers I can go off and generate a timetable .
question new_teacher_q
Please enter the name of the new teacher;
input name
because I need to know the name of the new teacher .
question subjects_q
Please enter the subject for the new teacher;
choose some of subjects
because I need to know what subjects they can teach .
question freetime_q
Which period is free? ;
choose one of period
because I need to know which period they have free .
question classes_q
Which classes can be taught? ;
choose some of class
because I need to know which classes they can teach .
frame listbox ;
default rows is 6 .
frame subjects_q_style is a listbox .
frame freetime_q_style is a listbox .
frame classes_q_style is a listbox .
% the following templates enhance the readability of the rules and
% relations.
% the following relations are used by both the timetable methods
% generate a class and a period which are not already allocated
relation class C needs timetabling for period P
if C is some class
and P is some period
and class C is not taught anything by anybody during period P .
% generate any teacher and subject for a given class and period
% according to the intitial data specifications
relation T can potentially teach S to class C during period P
if T is an instance of teacher
whose freetime does not include P and
whose subjects include S and
whose classes include C .
% generate a teacher and subject for a given class and period
% and test that they do not conflict with any previous allocations
relation T can definitely teach S to class C during period P
if T can potentially teach S to class C during period P
and T does not teach any C1 during P so is available to teach class C
and S is not taught to C at any other P1 so is available for period P .
% identify potential teacher conflicts due to teachers already being
% allocated to some class for a given period
relation T already teaches class C1 during P so cannot teach class C
if class C1 is taught something by T during period P
and C1 is different from C .
% identify potential subject conflicts due to subjects already being
% taught to a given class during some period
relation S is already taught to C during P1 which conflicts with period P
if class C is taught S by somebody during period P1
and P1 is different from P .
% forward chaining method
% the following ruleset first continually fires the extend_timetable rule
% until it can no longer be fired. This rule is then removed from the
% timetable and forward chaining continues with the two conflict
% resolving rules only
ruleset forward_chaining_timetable
contains extend_timetable,
resolve_teacher_conflict,
resolve_subject_conflict ;
select rule using first come first served ;
update ruleset by removing any unsatisfied rules .
% this rule generates a valid class, period, teacher and subject
% and then allocates this to the current timetable
rule extend_timetable
if class C needs timetabling for period P
and T can definitely teach S to class C during period P
then remember that class C is taught S by T during period P .
% this rule resolves potential teacher conflicts
rule resolve_teacher_conflict
if class C needs timetabling for period P
and T can potentially teach S to class C during period P
and S is not taught to C at any other P1 so is available for period P
and T already teaches class C1 during P so cannot teach class C
and T1 can definitely teach S1 to class C1 during period P
and T1 is different from T
then forget that class C1 is taught something by T during period P
and remember that class C1 is taught S1 by T1 during period P
and remember that class C is taught S by T during period P .
% this rule resolves potential subject conflicts
rule resolve_subject_conflict
if class C needs timetabling for period P
and T can potentially teach S to class C during period P
and T does not teach any OldC during P so is available to teach class C
and S is already taught to C during P1 which conflicts with period P
and T1 can definitely teach S1 to class C during period P1
and S1 is different from S
then forget that class C is taught S by somebody during period P1
and remember that class C is taught S1 by T1 during period P1
and remember that class C is taught S by T during period P .
% backward chaining method
% in the following relation the remembering of the class, subject,
% teacher and period is undone when no more teachers can be proposed
% for the remaining classes and periods
relation backward_chain_timetable
if class C needs timetabling for period P
and !
and T can definitely teach S to class C during period P
and remember that class C is taught S by T during period P
and backward_chain_timetable .
relation backward_chain_timetable .
% this action initiates the backward chaining solution.
action backward_chaining_timetable ;
do backward_chain_timetable
and write( 'computed using backward-chaining ...' ) and nl
and print_table .
% this action initiates the forward chaining solution.
action forward_chaining_timetable ;
do invoke ruleset forward_chaining_timetable
and print_timetable .
question timetable_method
Which method ? ;
choose one of 'forward chaining solution',
'backward chaining solution' .
% these actions print several views of the final timetable solution
action print_timetable ;
do show_teachers
and write( '<table border="0">' )
and write( '<caption><h3>Timetable</h3><//caption>' )
and write( '<tr><td valign="TOP" width="33%">' )
and print_classes
and write( '<//td><td valign="TOP" width="33%">' )
and print_teachers
and write( '<//td><td valign="TOP" width="33%">' )
and print_subjects
and write( '<//td><//tr><//table><br><br>' ) .
action print_classes ;
do write( '<table cellpadding=10><caption>Timetable Displayed by Class<//caption>' )
and write( '<tr><th>Period<//th><th>Subject<//th><th>Teacher<//th><//tr>' )
and
for every C is some class
do write( '<tr><td colspan=3 align="center" bgcolor="#ffffcc">' ) and write( C ) and write( '<//td><//tr>' )
and for every P is some period
and class C is taught S by T during period P
do write( '<tr><td>' )
and write( P )
and write( '<//td><td>' )
and write( S )
and write( '<//td><td>' )
and write( T )
and write( '<//td><//tr>' )
end for
end for
and write( '<//table>' ) .
action print_teachers ;
do write( '<table cellpadding=10><caption>Timetable Displayed by Teacher<//caption>' )
and write( '<tr><th>Period<//th><th>Subject<//th><th>Class<//th><//tr>' )
and
for every T is some teacher
do write( '<tr><td colspan=3 align="center" bgcolor="#ffffcc">' ) and write( T ) and write( '<//td><//tr>' )
and for every P is some period
and class C is taught S by T during period P
do write( '<tr><td>' )
and write( P )
and write( '<//td><td>' )
and write( S )
and write( '<//td><td>' )
and write( C )
and write( '<//td><//tr>' )
end for
end for
and write( '<//table>' ) .
action print_subjects ;
do write( '<table cellpadding=10><caption>Timetable Displayed by Subject<//caption>' )
and write( '<tr><th>Period<//th><th>Class<//th><th>Teacher<//th><//tr>' )
and
for every S is some subjects
do write( '<tr><td colspan=3 align="center" bgcolor="#ffffcc">' ) and write( S ) and write( '<//td><//tr>' )
and for every P is some period
and class C is taught S by T during period P
do write( '<tr><td>' )
and write( P )
and write( '<//td><td>' )
and write( C )
and write( '<//td><td>' )
and write( T )
and write( '<//td><//tr>' )
end for
end for
and write( '<//td><//tr><//table>' ) .