1
CALIFORNIA STATE UNIVERSITY, NORTHRIDGE
KNAP
THE
KN OWLEDGE-BASED
A UTOMATED
P ARLIAMENTARIAN
A graduate project submitted in partial satisfaction of
the requirements for the degree of Master of Science in
Computer Science
by
Alan G. Quan
May 1986
The Graduate Project of Alan Quan is approved:
Kenneth r1odesitt
Ronald Colman, Chair
California State University,
ii
~orthridge
Acknowledgments
I would like to thank the members of my committee,
Professor Ronald Colman, Professor Kenneth Modesitt, and
Professor John Guarrera, for their guidance and
suggestions.
Special thanks to Dr. Russell Abbott for
originally suggesting the project and for guiding its
early stages.
I must also thank Silogic, Inc. for
allowing me access to the company computer system and the
Silogic Knowledge WorkBench, on which my project is
implemented.
iii
Table of Contents
Chapter
Page
Approval Page
ii
Acknowledgments
iii
Abstract
vii
1.
2.
3.
Introduction
1
1.1
Expert Systems
1
1.2
Robert's Rules of Order
4
System Overview
19
2.1
System Architecture
19
2.2
System Functions
23
Knowledge Base
29
3.1
Knowledge Representation Language
30
3.1.1
Prolog
30
3.1.2
PKRL
32
3.1.2.1
Relations
35
3.1.2.2
Attributes
36
3.1.2.3
Boolean Attributes
38
3.1.2.4
Context Tuples
3.1.2.5
Log Entries
41
3.1.2.6
Negations
41
iv
.40
4.
5.
Askable Predicates
42
3.1.2.8
Unique Identifiers
43
3.2
Domain Model
46
3.3
State Model
51
3.3.1
State Representation
52
3.3.2
Context Maintenance
58
Rule Interpreters
61
4.1
Prolog Rule Interpreter
62
4.2
Explanation Rule Interpreter
70
4.3
Consultation Mode Interpreter
75
4.4
Default Reasoning
80
Input Processing
82
5.1
User Interface
83
5.2
Actions
84
5.3
Queries
100
5.4
6.
3.1.2.7
5.3.1
Yes/No Queries
100
5.3.2
WH Queries
101
Commands
102
Concluding Remarks
105
v
References
109
Appendices
A.
Code Listing
111
B.
Sample Session Transcript
180
vi
ABSTRACT
KNAP
THE
KN OWLEDGE-BASED
A UTOMATED
P ARLIAMENTARIAN
by
Alan G. Quan
Master of Science in Computer Science
This report describes the design and implementation of
KNAP,
a knowledge-based expert system that can serve as
an automated parliamentarian (i.e., an advisor for
parliamentary procedure in a deliberative assembly).
The
expert knowledge of the system is derived from Robert's
Rules of Order, a standard guide for parliamentary
procedure.
KNAP implements a subset of Robert's Rules of
Order dealing with introduction of business,
classification of motions,
order of precedence and
debate of motions, and voting.
The system is written
entirely in Prolog and includes a backward-chaining
inference engine, a consultation mode, a declarative
knowledge base, explanations of results, and a knowledge
base query capability.
Suggestions for future
enhancements of the system are given.
vii
Chapter 1
Introduction
1.1
Expert Systems
An expert system is a computer program that
contains the knowledge of a specialized domain and
possesses problem-solving expertise for that domain.
These systems are used to solve complex problems or
perform difficult tasks that in the past have been
reserved for human experts.
An expert system should at
least equal the level of correctness of a human expert
and exceed the human expert in terms of speed.
Expert
systems are often designed to be used by people
unfamiliar with the system's domain.
Existing expert systems perform a variety of
tasks,
including mineral prospecting (PROSPECTOR) [Duda
et al,
1979], blood disease diagnosis (MYCIN)
[Shortliffe,
1976], chemical structure identification
1
(DENDRAL) [Buchanan and Feigenbaum, 1978], computer
configuration (XCON) [McDermott, 1982], symbolic
mathematics (MACSYMA) [Martin and Fateman, 1971], and
molecular genetics experiment design (MOLGEN) [Stefik
1981a, 1981b].
The tasks performed by expert systems can be
classified into a few generic categories (taken from
Hayes-Roth, 1983):
1.
Interpretation
- Inferring situation descriptions
from sensor data.
2.
Prediction
-
Inferring likely consequences of given
situations.
3.
Diagnosis
- Inferring system malfunctions from
observable data.
4.
Design
-
5.
Planning
6.
Monitering
Configuring objects under constraints.
- Designing actions.
- Comparing observations to plan
vulnerabilities.
7.
Debugging
8.
Repair
-
- Prescribing remedies for malfunctions.
Executing a plan to administer a prescribed
remedy.
9.
Instruction
-
Diagnosing, debugging, and repairing
student behavior.
Interpreting, predicting, repairing, and
10. Control
monitoring system behaviors.
Knowledge is essential for solving difficult
problems and hence is a key ingredient in expert systems.
The facts,
rules, and theories of a domain of knowledge
are translated into some internal, machine recognizable
representation and stored collectively in a
base •
knowledge
The knowledge base is a distinct component of an
expert system,
of the system.
classified as
distinguished from the procedures and data
For this reason expert systems are
knowledge-based
systems.
4
1.2
Robert's Rules of Order
Parliamentary Law consists of the customs and
rules for conducting business in a deliberative assembly.
Its chief purpose is to expedite the resolution of
business that has been taken up by such an assembly.
most widely used guide for Parliamentary Law is
Rules of Order
The
Robert's
[Robert, 1979].
Robert's Rules of Order (RROO) has two primary
rules:
1) Only one person may speak to the assembly at a time.
2) Only one topic or issue may be considered by the
assembly at any particular time.
The basic unit of business in RROO is the
motion .
Below is a list of some of the types of motions governed
by Robert's Rules of Order along with their intended
purposes:
Objective
Motion Type
Introduce business.
Main Motion
Defer or kill a motion.
Postpone
Indefinitely
Defer action.
Postpone to a Set
Time
Make a Special
Order of the
Day
Lay on the Table
Change or modify.
Amend
Let a few attend to a matter.
Commit
Stop debate and order an
immediate vote.
Suppress a question.
Previous Question
Object to
Consideration
Postpone
Indefinitely
6
Do something contrary to the Rules.
Suspend the Rules
Prevent a motion from being
voted on.
Withdraw
Consider a motion a second time.
Take from the
Table
Reconsider
Rescind
Object to a decision of the Chair.
Appeal
Ask a question or make a point
of order.
Question of
Privilege
Dismiss a meeting.
Adjourn
Set a time for a future meeting.
Fix Time to which
to Adjourn
To enable adherence to the primary rules, RROO
sets out a complex set of rules governing the order of
speakers and the order and
precedence
of the various
7
types of motions that may be considered by a deliberative
assembly.
To make a motion (i.e., bring business or
information before the assembly for consideration) a
member must first ''obtain the floor"
to speak).
(be given permission
The Chairman (presiding officer) of the
assembly grants the floor to a speaker if no one else has
the floor,
or if the speaker is making a motion that may
interrupt someone who already has the floor.
Once a
speaker has the floor s/he may debate the immediately
pending motion or may make a new motion.
The Chairman
decides whether a new motion is in order (may be
considered by the assembly) at that time.
If the new
motion is in order then it becomes the immediately
pending motion and the Chairman and/or assembly may take
further action on that motion.
Once a motion has been considered by the assembly
it may then be resolved (adopted or rejected).
Some
motions are resolved by a decision of the Chair, and
others by a vote of the entire assembly.
A motion may
also be disposed of in other ways (e.g., referred to a
committee, "laid on the table'').
are regulated by RROO.
All of these actions
8
RROO is an area of expertise for which an expert
system does not yet exist, although such a system would
be very useful.
The presiding officer of a deliberative
body (e.g., a legislature) that follows RROO often does
not have a complete knowledge of RROO.
To allow accurate
and fair rulings on matters of procedure, the officer
consults with an expert on parliamentary law called a
parliamentarian.
An expert system could embody the
knowledge of RROO and serve as an automated
parliamentarian, monitering the actions performed by a
deliberative assembly and advising the presiding officer
as to their legality.
The actions regulated by RROO include:
Introduction of business before the assembly.
Classification of Motions.
Order of precedence of Motions.
Debate of Motions.
Voting.
Organization and Actions of committees.
The debate and resolution of motions in
particular give rise to complicated questions of order
that must be ruled upon by the presiding officer.
Whenever a "main motion" is made (to bring new business
9
before the assembly) it may engender a number of
subsidiary and incidental motions that are related to the
main motion and must be considered before any further
action is taken on the main motion.
Some of these
motions may themselves be subject to subsidiary motions,
may be debatable,
or may require approval by a specified
majority of the assembly.
One of the parliamentarian's
duties is to advise the presiding officer as to the
proper order and procedure for resolving motions.
Order of precedence of a motion is an important
factor.
with it.
Ea~h
type of motion has a precedence associated
Higher precedence motioris that are pending must
be resolved before motions of lower precedence.
Below is
a list of the motion types dealt with by RROO in order of
precedence (motion types higher in the list have higher
precedence than those lower in the list, unless otherwise
indicated):
Privileged Motions:
Fix Time to which to Adjourn
Adjourn
Take a Recess
10
Questions of Privilege
Call for Orders of the Day
Incidental Motions:
(No precedence among themselves)
Questions of Order and Appeal
Suspension of the Rules
Objection to the Consideration of a Question
Division of a Question
Division of the Assembly
Motions Relating to Nominations
Requests Growing out of the Business of the Assembly
Subsidiary Motions:
Lay on the Table
The Previous Question
Limit of Extend Limits of Debate
Postpone Definitely
Commit or Refer
Amend
Postpone Indefinitely
11
Main Motions
(including Ratify, Renewal of Motion, Rescind,
Take from Table)
Below is a portion of a hypothetical session of a
deliberative assembly.
It illustrates some of the
complexities and interdependencies that may arise out of
RROO.
At various points during the session the Chairman
must make decisions about the actions taking place.
The
questions that the Chairman must decide are enclosed in
braces({}):
Member #18 obtains the floor.
{May member 18 be given the floor?}
Member #18 makes a Main Motion (ID #1):
"To halt deplqyment of nuclear weapons in Europe."
Member #24 sedonds the Motion.
12
,, .
{Is motion 1 in order at this time?}
The Chair rules motion #1 to be in order.
The Chair states motion #1 to the assembly.
Member #15 makes an Incidental Motion (ID #2):
Objection to Consideration of the Question.
{May member 15 make a motion without having the
floor?
Is motion 2 in order?}
The Chair rules motion #2 to be in order.
The Chair states motion #2 to the assembly.
Member #15 yields the floor.
{May another member debate motion 2 or is it
undebatable?}
The Chair puts motion #2 to the assembly for
vote (motion #2 is not debatable).
13
{Does motion 2 need a two-thirds majority to
pass or a simple majority?}
The assembly votes to defeat motion #2.
Member #12 obtains the floor and states her
opinion on motion #1.
{May member 12 have the floor?
Is motion 1 debatable?}
Member #9 makes a Subsidiary Motion (ID #3):
To Postpone motion #1 to a set time.
{May
me~ber
9 interrupt member 12?
Is motion 3 in order?}
The. Chair rules that member #9 is out of order
because a Motion to Postpone to a set time cannot
interrupt a speaker who has the floor.
Member #12 concludes her remarks and relinquishes
the floor.
Member #33 obtains the floor and makes a
Subsidiary Motion (ID #4):
14
To Amend motion #1 to read:
"To advise the
President to halt deployment of nuclear weapons
in Europe."
Member #19 seconds the motion.
(May member 33 have the floor?
Is motion 4 in order?}
The Chair rules motion #4 to be in order.
The Chair states motion #4 to the assembly.
Member #33 states his opinion on motion #4
and relinquishes the floor.
(May member 33 debate motion 33 or is it
undebatable?}
Member #12 obtains the floor and makes a
Subsidiary Motion (ID #5):
To Limit Debate on motion #4 to 1 hour.
Member #26 seconds the motion.
(May member 12 have the floor?
15
Is motion 5 in order?}
The Chair rules motiori #5 to be in order.
Member #12 yields the floor.
The Chair states motion #5 to the
assembly.
(May another member debate motion 5 or is
it undebatable?}
The Chair puts motion #5 to the assembly
for vote (motion #5 is not debatable).
(What size majority does motion 5 need in
order to pass?}
The assembly votes in favor of motion #5.
Member #49 obtains the floor and makes a
Subsidiary Motion (ID #6):
To Postpone motion #1 Indefinitely.
(May member 49 have the floor?
Is motion 6 in order?}
16
The Chair rules motion #6 to be out of order
because a motion with higher precedence
(motion #4) is under consideration.
Member #49 yields the floor.
Member #56 obtains the floor and makes a
Subsidiary Motion (ID #7):
To Refer motion #1 to a Committee.
Member #44 seconds the motion.
{May member 56 have the floor?
Is motion 7 in order?}
The Chair rules motion #7 to be in order.
Member #56 yields the floor.
The Chair states motion #7 to the
assembly.
{May another member debate motion 7 or is
it undebatable?}
17
The Chair puts motion #7 to the assembly
for vote (motion #7 is not debatable).
{What size majority does motion 7 need in
order to pass?}
The assembly votes in favor of motion #7.
{Which motions in addition to motion 7
should be sent to committee?}
Motion #1 and its adhering motion #4 are
referred to a committee.
KNAP,
the Knowledge-based Automated
Parliamentarian, is an expert system that can serve as an
automated parliamentarian for a deliberative assembly
governed by RROO.
as
monitoring .
KNAP's primary task can be classified
KNAP is written entirely in Prolog
(Silogic Knowledge WorkBench version 1.11).
implements a subset of RROO dealing with:
It
18
1)
Introduction of business before the assembly.
2)
Classification of Motions.
3)
Order of precedence of Motions.
4)
Debate of Motions
5)
Voting
Chapter 2
System Overview
2.1
System Architecture
KNAP has five major components:
1.
User Interface
2.
Explanation Rule Interpreter
3.
Consultation Mode Interpreter
4.
System Procedures
5.
Knowldege Base (Domain and State Models)
Below are two diagrams showing module organization and
system data flow:
19
20
Figure 1 - KNAP Organization Diagram
USER
I~TERFACE
1
SYSTEM
<------
PROCEDURES
EXPLANATION
RULE
INTERPRETER
----->
<.-----
CONSULTATI0:-!
MODE
INTERPRETER
____________l __
----~
STATE MODEL
--------------q
DOHAIN MODEL
A calls B
A accesses data in B
1
1
21
Figure 2 -
KNAP Data Flow Diagram
--------------USER
inputl
question
~----------------
~answer
goal
answer
USER
------------>
INTERFACE
answer
goall
~answer
-------------SYSTEM
------------goal -------------goal
-------~
{------- EXPLANATION .(------- CONSULTATION
RULE
answer
MODE
goal
-------) INTERPRETER
INTERPRETER
answer
-------)
------------- answer --------------
<-------
PROCEDURES
i---->1
f acts
factsl
----------------STATE MODEL
clauses
clauses
_______________ ,
DOMAIN MODEL
The User Interface (UI) is a simple command
interpreter that takes input (state updates,
queries,
and commands) from the user, executes it,
and returns an answer or response.
To execute
state updates the UI calls the Explanation Rule
22
Interpreter.
To execute queries the UI attempts to
prove Prolog goals directly.
To execute commands
the UI calls System Procedures and Prolog system
predicates.
The Explanation Rule Interpreter (ERI) processes
state updates by retrieving information from the
Knowledge Base and by calling System Procedures and
the Consultation Mode Interpreter.
It also
generates an explanation of the steps taken during
this processing.
The Consultation Mode Interpreter (CMI) proves
goals sent to it by the ERI.
It does this by
calling the ERI and, when necessary, asking the
user whether the goal is true.
Only State Model
goals are proven by the CMI.
The System Procedures (SP) consist of all
procedures not included in the UI, ERI, or CMI.
These are called directly by both the UI and the
ERI.
The Domain Model (DM) and State Model (SM) make up
the KNAP knowledge base.
The DM contains all the
knowledge of the subset of RROO handled by KNAP.
23
The SM is an internal representation of the current
state of the assembly.
These components are described in detail in later
chapters.
2.2 System Functions
KNAP's main function is to act as a parliamentary
''referee".
During a meeting of a deliberative assembly
KNAP works interactively with the user.
The user can be
either a secretary who is monitoring the meeting or the
Chairman of the assembly.
Each time a new
action
is
performed by the assembly the user enters this event into
the system through the User Interface.
An action is an
official act performed by one or more members of the
assembly or by the Chairman.
actions accepted by KNAP:
The following are valid
24
Performed By
Action
1.
Obtain the floor.
Member
2.
Yield the floor.
Member
3.
Make a motion.
Member
4.
State the current question.
Chairman
s.
Debate a motion.
Member
6.
Resolve a motion
(for motions that do not require a vote).
7.
Chairman
Put the current question to the assembly
(for a vote).
Chairman
8.
Vote on a motion.
Member
9.
Dispose of a motion.
Chairman
Based on this input KNAP maintains an internal
representation of the current state of the assembly,
called the State Model.
Information relevant to the
current state includes:
1.
Member who currently has the floor (if any).
2.
Motion currently under consideration.
3.
Status of the
curr~nt
motion.
(e.g., is the motion being debated, voted on,
1
etc.).
25
4.
Motions pending but not immediately under
consideration.
5.
All motions that apply to a particular pending
motion.
6.
Whether a motion has been seconded.
7.
Whether a motion is of urgency.
8.
The method of voting used on a motion.
9.
History of actions performed by the assembly.
Each action entered into the system is treated as
an attempted state update.
Using the knowledge of RROO
contained in the Domain Model, KNAP examines each
attempted update within the context of the current
assembly state to determine if it is legal.
If the
update is judged legal according to RROO then KNAP
accepts it and changes the internal state representation
accordingly.
Otherwise KNAP rejects the update and
outputs an error message to the user with a brief
explanation of why the action is illegal.
In this way
KNAP monitors the activity of the assembly and acts like
a referee, "blowing the whistle'' whenever there is a
violation of proper parliamentary procedure.
The user also has the option of asking a query
about the contents of the knowledge base or executing a
26
KNAP or Prolog system command.
There are several
predefined KNAP commands that aid in displaying the
knowledge base and in explaining system rulings on state
updates.
All Prolog system predicates are available to
the user.
Below is a flow chart for KNAP's top level
execution loop:
27
FIGURE 3 - Flow Chart For Top Level Execution
BEGIN
~
READ
~-----------------------------------------
INPUT
_L
I
\
I INPUT IS \
I UPDATE \
A STATE
\
~I
IS
\
,
UPDATE
1-y..----7-7"\\ LEGAL
l~y...----;r-7
\
N
I
\T/
REJECT UPDATE
AND
INFORM USER
\
INPUT IS \
,
--y--------7~
A
QUERY
1
\
\ _ _-.---__1
I
I
STATE
-----------------)>
ANSWER
QUERY
UPDATE
------------->
Nr
I
\
I
\
I
\
INPUT IS \
,1 INPUT IS \
A COMMAND 1-=-Y---;r-7':\ "HALT" 1--=-y--)?
\_---=N-r--_1
\T/
EXECUTE
COMMAND
GIVE
ERROR
MESSAGE
OUTPUT
MINUTES
AND HALT
-----------------~
28
Chapter 3
Knowledge Base
The KNAP knowledge base is divided into two major
components: the
Domain Model
and the
State Model .
The Domain Model contains the static knowledge of RROO.
This domain information does not change from session to
session.
The State Model contains those facts which make
up the internal representation of the current state of
the assembly.
This situation specific information is
constantly changing during the course of a session and is
usually not retained at session's end.
At run time the
Domain Model is loaded in from a file and resides in main
memory with the State Model.
The knowledge of both
Models is expressed in terms of the Parliamentary
Knowledge Representation Language (PKRL).
30
3.1
Knowledge Representation Language
The knowledge representation language
~f
KNAP,
PKRL, is an extended version of Silogic's Knowledge
WorkBench Prolog.
This Prolog has been extended to
include an explicit syntax for the different types of
predications that exist in the KNAP knowledge base.
3.1.1
Prolog
Prolog is a declarative programming language
based on first order predicate logic.
It follows the
logic programming convention of representing statements
as Horn clauses [Lloyd, 1984], where the positive literal
is written to the left of the symbol ":-'' and the other
terms are written to the right.
For example, the clause
p(X) v -q(X) v -r(X)
is represented in Prolog as the Horn clause
p(X)
-
q(X),
r(X).
31
which is equivalent to the first order formula
q(X)
& r(X) --> p(X)
The term to the left of ":-" is called the
head
of the
clause and the expression to the right is called the
body •
The comma (,) corresponds to the logical AND
connective and the semicolon (;) corresponds to the
logical OR.
Prolog horn clauses can also be read as
implications, where the consequent is the head and the
antecedent is the body.
The symbol ":-" can be read as
"if" and can be thought of as a leftward pointing
implication arrow.
Universal quantification over a first order
formula is easily represented in Prolog following the
standard formula-to-clause conversion techniques
[Nilsson, 1980].
Thus the formula:
~X [man(X)
-->
mortal(X)]
("All men are mortal.")
is represented in Prolog clause form as
mortal(X)
:- man(X).
32
The universal quantifier is dropped and the variables
bound by the universal remain uninstantiated.
A unit clause, called a
fact , is represented in
Prolog as a single predicate (e.g., p(X)) with no":-" or
body.
A fact is equivalent to a rule with a true body
(e.g., p(X) :-true).
3 .1. 2 PKRL
Following is the BNF definition for PKRL:
,,
33
<clause>
.. -<rule)
<fact>
I
<fact>
.. <predicate>
<rule>
.. -<consequent> :- <antecedent>
<consequent>
.. -<predicate>
<antecedent>
.. -<goal expression)
<goal expression>
.. --
<goal predicate>
<goal predicate>, <goal expression>
<goal predicate>
.. -( <goal expression>;<goal expression>
not <goal predicate>
I
<prolog system predicate>
<predicate>
<prolog system predicate>
.. --
)I
'
34
(a Prolog system predicate, e.g., =/2,
member/2, forall/2)
.. --
<predicate>
<p_predicate>
I
(context tuple>
<log entry>
<negation>
I
<askable predicate)
<p_predicate)
.. -<relation>
<attribute>
I
<boolean attribute)
<negation>
.. -false(
<askable predicate)
<p_predicate) )
.. --
askable( <p predicate) )
The symbols ":-", ",", and ";' have the precedences
normally associated with -->, A, and v respectively.
PKRL <predicate>'s are based on the
35
entity-relationship model [Ullman, 1980].
There are two
kinds of objects about which these predications can be
made:
3.1.2.1
entities
(nouns), and
values
(adjectives).
Relations
A
relation
predicate associates one
entity
with another:
Entity(!) ----- <Relation> ----- Entity(2)
An entity is a proper noun for a thing or animate. being.
A relation is usually a verb.
predicate is the relation name.
The functor of a relation
The general format of a
relation predicate is
Relation(Entity(l), Entity(2))
An example of a relation is "loves" in the assertion
"Peter loves Diane."
Peter ----- <loves> ----- Diane
36
In PKRL this assertion is represented as
loves(Peter, Diane).
A KNAP domain example of a relation is "applies to" in
the the assertion
"motion 4 applies to motion 8."
-
-
motion 4 ----- <applies_to> ----- motion 8
which in PKRL looks like
applies_to(motion_4, motion_8).
3.1.2.2
Attributes
An
with an
attribute
predicate associates an entity
attribute value :
Entity ----- <Attribute> ----- Value
An attribute value is an adjective (e.g., red, happy,
wealthy) and an attribute is a name for a set of
37
attribute values (e.g., color, mood, economic status).
The functor of an attribute predicate is the attribute
name.
The general format of an attribute predicate is
Attribute(Entity, Value)
An example of an attribute is "color" in the assertion
"The color of Felix is black"
Felix
<color> ----- black
color('Felix', black).
A KNAP domain example of an attribute is "order" in
"The order of motion 9 is 'pending'."
motion_9 ----- <order) ----- pending
order(motion_9, pending).
38
3.1.2.3
Boolean Attributes
Sometimes it is useful to consider attributes
that have only two possible values, one of which is the
negation of the other.
For example, the attribute
"sanity" might have only two values, "sane" and ''insane",
when referring to world leaders.
For knowledge
representation purposes in this case it is convenient to
drop the attribute name and use only one of the attribute
values as a predicate name.
attributes are called
In PKRL these kinds of
boolean attributes •
A boolean
attribute associates an entity or set of entities with a
truth value of ''true" for a particular attribute value:
Entity Set ----- <Attribute Value> ----- true
The general format of a boolean attribute is
AttributeValue(Entity(l), Entity(2),
••• , Entity(N)).
For example, the assertion
"Margaret Thatcher is sane"
can be r presented in PKRL as
39
sane('Margaret Thatcher')
If the negation of the attribute value applies to
an entity (i.e., the value not chosen as a predicate
name) then .no assertion is made.
So if we wanted to
express the assertion, "Mohamar Khadafi is not sane"
(i.e., he is insane), we would simply make no assertion.
The absence of the assertion
sane('Mohamar Khadafi')
means that it is false that Mohamar Khadafi is sane.
This follows the standard Prolog strategy of
failure
negation as
[Clocksin and Mellish, 1981] which applies to
boolean attributes, except when they are used as askable
predicates or in default reasoning (see Chapter 4).
Although the ''law of the excluded middle" (i.e., X v
X)
is incorrect for many domains, it is an appropriate and
useful assumption for KNAP.
If a boolean attribute value
is not provable for an entity then its negation is
assumed true.·
The arguments of a boolean attribute are
the elements of an n-tuple where n
>
0.
Here are some KNAP domain examples of boolean
attributes:
40
"motion 12 is debatable"
motion 12 ----- <debatable> ----- true
debatable(motion_12)
"motion_22, which was moved by member_19 and
applies to motion_3, is in order.
{motion_22, member_19, motion_3}-----(in_order> -----true
in_order(motion_22, member_19, motion_3)
3.1.2.4
Context Tuples
A
context tuple
is similar to a tuple of a
relation in a standard relational database.
It is a
three-argument predicate with "context" as functor.
"fields" of the tuple are:
1.
The status of the motion before the assembly.
2.
The ID of the motion before the assembly.
3.
The member of the assembly who has the floor.
Section 3.3.2 describes how context tuples are used.
The
41
3.1.2.5
Log Entries
Log entries
are used to maintain a history of
all events that have occurred during a particular
session.
Many domain rules refer to past events via log
entries.
A log entry is added to the State Model each
time a state update is attempted.
The general format for
a log entry is
log( <history predicate>, (time tag> ).
3.1.2.6
Negations
A
negation
is a unary predicate with "false" a$
functor and any p_predicate as argument.
It expresses
the logical negation of the p_predicate.
The assertion
"motion 13 is not applicable to motion 11"
is represented as a negation in PKRL:
42
false(applicable to(motion 13, motion 11)).
-
-
-
Negations are used for askable predicates and default
reasoning,
3.1.2.7
Askable Predicates
An
11
explained in Chapter 4.
askable predicate
is a unary predicate with
ask able 11 as functor and any p_predica te as argument.
is both procedural and declarative in nature.
Askable
predicates appear only as goals in the bodies of rules.
For any askable predicate askable(P), if P is not
provable from the knowledge base then the user is asked
about the truth value of P.
thoroughly in Chapter 4.
This is explained more
I.t
43
3.1.2.8
Unique Identifiers
All entities in PKRL are represented by unique
identifiers.
in KNAP:
There are two kinds of entities referred to
motions
and assembly
members •
A motion is
represented by a term
<ID>:<Rule Num>
where <ID> is a unique integer and <Rule Num> has the
form
r<Number).
<Rule Num> identifies the specific type of which motion
<ID> is an instance.
<Number> is the rule number
associated with the motion type as stated in RROO.
example, a motion to
For
Suspend the Rules (rule number 22
in RROO), having <ID> 311, is represented as
311:r22.
The <Rule Num> enables immediate identification of a
motion's type, allowing the rule interpreter to select
only those clauses that are pertinent to a particular
44
motion (see Chapter 4).
This is similar to the "x:T"
notation used by Frisch [Frisch, 1985] for restricted
quatification, where x is a variable that is instantiated
to an instance from "sort" T (a subset of the universe).
Members of the assembly are represented either by unique
atoms (names) or unique integers.
A single entity cannot
have more than one identifier and no two entities may
share the same identifier.
Below is a list of motion types handled by KNAP
and their <Rule Num>'s:
Motion
<Rule Num>
Fix Time to Adjourn
r16
Adjourn
r17
Recess
r18
Question of Privilege
r19
Call for Orders of the Day
r20
Appeal
r21a
Question of Order
r2lq
Suspension of the Rules
r22
Objection to Consideration of a Question
r23
Division of a Question
r24
Division of Assembly
r25div
45
tl '
Motions Related to Voting
r25
Method of Nominations
r26meth
Close Nominations
r26close
Reopen Nominations
r26reop
Parliamentary Inquiry
r27info
Withdraw a Motion
r27cw
Modify a Motion
r27cm
Reading Papers
r27d
Lay on the Table
r28
Previous Question
r29
Limit or Extend Limits of Debate
r30
Postpone Definitely
r31
Commit or Refer
r32
Amend
r33
Postpone Indefinitely
r34
Take from Table
r35
Reconsider
r36
Rescind, Repeal, or Annul
r37
Main Motion
main
The numerical part of the <Rule Num> is the same as the
rule number assigned to the corresponding motion in
Robert's Rules of Order, Revised
[Robert, 1979].
Further information on each motion can be obtained by
consulting the appropriate rule number in that text.
46
3.2 Domain Model
The subset of RROO handled by KNAP is called the
Domain Model.
these rules.
It consists of the PKRL representation of
These rules embody the "permanent"
knowledge of KNAP;
they will always be true regardless of
the situation to which they are applied (they remain
unchanged from session to session).
The Domain Model
contains the laws of parliamentary procedure which KNAP
uses to determine the legality of state updates.
Following is a list of the primary Domain Model
predicates with a brief description of each:
Predicate:
amendable( X)
Type:
boolean attribute, fact or rule.
Meaning:
Motion X is amendable.
Predicate:
applicable to(X, Y)
47
Type:
relation,
fact or rule.
Meaning:
Motion X may be applied to motion Y (an
auxiliary predicate called by in_order/3).
Predicate:
debatable(X)
Type:
boolean attribute, fact or rule.
Meaning:
Motion X is debatable.
Predicate:
decidable_by_chair(X)
Type:
boolean attribute, fact.
Meaning:
The disposition of motion X may be
decided by the Chairman without an assembly vote.
Predicate:
eligible_for_consideration(X, Y)
Type:
boolean attribute, fact or rule.
Meaning:
Motion X, as it applies to motion Y, is
currenty eligible for consideration (auxiliary
predicate called by in_order/3).
48
Predicate:
in_order(X, M, Y)
Type:
boolean attribute, rule.
Meaning:
The tuple consisting of the motion X,
the member M, and the motion Y to which X
applies, is currently in order.
Predicate:
may_have_floor(M)
Type:
boolean attribute, rule.
Meaning:
Either member M has the floor or no one
has the floor.
Predicate:
motion_class(N, C)
Type:
attribute, fact.
Meaning:
The motion class of motion rule number
N is C.
Predicate:
Type:
(e.g., motion class(rl6, privileged)).
needed_to_pass(X, V)
attribute, fact.
49
Meaning:
Motion X needs a vote of size V in
order to pass (e.g.,
needed_to_pass(XID:r22, two_thirds)).
Predicate:
orderly introduction(X, M)
Type:
boolean attribute, rule.
Meaning:
Motion X has been introduced to the
assembly in an orderly fashion by member M (an
auxiliary predicate called by in_order/3).
In addition the Domain Model also contains the
action
predicates , which are described in Chapter 5.
The translation of an English RROO rule to a PKRL
Domain Model rule is a straightforward one.
A typical
RROO rule can be easily transformed into a conditional
statement of the form "<conclusion) IF <condition>."
This conditional is then translated into a Prolog horn
clause using the appropriate PKRL primitives.
example of an RROO rule expressed in English:
Here is an
so
Any Motion to Lay on the Table X, made by any member M,
applied to any other motion Y, is in order if:
M may have the floor,
AND
X is seconded,
AND
Either Y is a privileged motion OR
There are no privileged motions currently
pending,
AND
Y is currently pending, AND
X is "applicable to" Y.
Here is the same rule as it appears in the Domain Model:
in order(X:r28, M, Y) :may_have_floor(M),
askable(seconded(X:r28)),
(motion class(Y, privileged);
not class status(privileged, pending)),
order(Y, pending),
applicable_to(X, Y).
X,
Y, and M are variables that can unify with Prolog
terms.
X will unify with a unique motion ID (integer)
and Y will unify with an <id>:<rule-num) pair.
M will
unify with a unique ID for an assembly member.
The
predicates motion class and applicable_to are satisfied
by facts or rules elsewhere in the Domain Model.
The
other predicates in the body of the rule are satisfied by
facts,
Model.
or procedures that access facts,
in the State
The Domain rules usually must access State Model
facts at some point, either directly or through calls to
other Domain rules.
A complete listing of the KNAP
51
Domain Model can be found in Appendix A.
3.3
State Model
The KNAP State Model contains facts that
represent the current state of the assembly.
Every time
the user makes a state update, the facts of the State
Model are changed in some way.
Most of the time new
facts will be added to the knowledge base.
For example,
whenever a new motion is made by a member of the assembly
and this motion is found to be in order, several new
facts are added to the State Model.
One of these facts
tells who made the motion, another says that the motion
is currently in order, another tells which motion this
new motion applies to, if any.
deleted as a result of a state
yields the floor.
Facts might also be
update~
as when a member
All relevant actions made by the
assembly are reflected in the State Model in this way.
Since new actions are constantly being performed by the
assembly, the
int~rnal
representation is constantly
changing.
State Mod 1 facts constitute the variable part of
52
,,
the proof of a Domain Model rule.
For any KNAP goal that
unifies with the head of a Domain rule, and for any given
set of parameters, the provability of the goal will vary
according to the State Model facts that are true when the
goal is launched (this process is explained in detail in
Chapter 4).
3.3.1
State Representation
As mentioned in Chapter 2 there are a number of
facts that collectively describe the current state of the
assembly.
fact.
Each of these facts is represented by a PKRL
These facts are divided into three categories:
1.
Facts about motions that are under consideration.
2.
Other facts about the current state of the
assembly.
3.
Facts about past actions performed by the
assembly
(history) that may affect the outcome of current
actions.
'
53
The primary State Model predicates are described
below:
1.
Facts about Motions
Predicate:
applies_to(X, Y)
Type:
relation
Meaning:
Motion X is being applied to motion Y.
Predicate:
decided(chair, M)
Type:
relation
Meaning:
The Chairman has made a decision on
motion M.
Predicate:
order(X, Order)
Type:
attribute
Meaning:
If motion X is pending then
order(X, pending)
is true.
If motion X is immediately pending
("active") then
54
order(X, active)
is true.
This is actually a procedure that
accesses the top context tuple in the pending
stack (see section 3.3.2)
Predicate:
relates_to(X, Subj)
Type:
relation
Meaning:
Motion X is related to subject Subj.
(e.g., relates_to(ID:r21a,
Predicate:
'rules of speaking')).
seconded(X)
Type:
boolean attribute
Meaning:
Motion X has been seconded.
Predicate:
urgency(X, immediate)
Type:
attribute
Meaning:
Motion X is of immediate urgency to the
assembly.
Predicate:
voted_for(M, X)
55
Type:
relation
Meaning:
Member M voted for motion X.
Predicate:
voted_against(M, X)
Type:
relation
Meaning:
Member M voted against motion X.
Predicate:
voting_method(X, Meth)
Type:
attribute
Meaning:
The method of voting used to resolve
motion X is Meth.
e.g.,
voting method(ID:Num, viva voce)).
-
2.
Other Current Facts
Predicate:
Type:
context(St, X, M)
context tuple
-
56
Meaning:
Motion X is immediately pending. The
''assembly state" is St. Member M currently has
the floor.
Predicate:
assembly state(St)
Type:
special
Meaning:
The current ''assembly state" is St.
This is actually a procedure that accesses the
top context tuple in the pending stack (see
section 3.3.2).
Predicate:
has_floor(M)
Type:
boolean attribute
Meaning:
Member M currently has the floor.
This actually a procedure that accesses the top
context tuple in the pending stack (see section
3.3.2).
57
3.
History of Actions
Predicate:
log(E, T)
Type:
log entry
Meaning:
Event E took place at time T in the
sequence of events.
KNAP maintains only a skeletal representation of
the assembly state since no more is necessary to resolve
questions of parliamentary procedure.
The form of
motions is more important than their content in RROO, and
only those general bits of content information that are
germane to RROO are actually recorded in the knowledge
base.
No attempt is made to keep online copies of any
part of the text of motions.
58
3.3.2
Context Maintenance
Some motions have higher precedence than others.
If a motion is under consideration and another motion
with a higher precedence is made (assuming it to be in
order at that time), all activity related to the original
motion must be temporarily suspended and the new motion
must be immediately taken up by the assembly.
This
second motion may in turn be suspended if another motion
with an even higher precedence arises.
Once the higher
precedence motion is resolved, the motion that was
previously suspended by the higher motion is again taken
up by the assembly, at the point where it was left off.
To handle motions of different precedences KNAP
employs the concept known as
context switch , borrowed
from operating system theory [Peterson, 1983].
The
immediately pending motion is called the
active
All other pending motions are
motions.
suspended
motion.
KNAP
maintains a stack of predicates, called
context tuples ,
with one tuple for each pending motion.
A context tuple
has the form
context(State, Motion, Member)
59
Motion is the unique ID of the pending motion.
For
suspended motions State is the assembly state at the time
when the motion was last active and Member is the ID of
the member of the assembly who will have the floor when
the motion becomes active again.
For active motions
State is the current assembly state and Member is the
member who currently has the floor.
At the Prolog level
the stack looks like this:
stack(pending, [Cxt(l), Cxt(2),
••• , Cxt(n)]).
Where Cxt(x) is a context tuple.
Whenever a new motion is made, a context tuple
for that motion is pushed onto the stack.
The active
context tuple is always on the top of the stack.
Any
updates to the active motion, assembly state, or floor
are made directly to the active context tuple.
When a
higher precedence motion arises, a context switch occurs.
The context tuple of the higher motion is pushed on top
of the previous context tuple, thus activating the new
motion while suspending the previous motion.
After the
higher precedence motion is resolved its context tuple is
popped off the stack.
This allows the previous motion to
rise back to the top of the stack and thereby become
active again.
60
The stack is manipulated through the procedures
update_floor/1, update_pending/2, update_state/1, pop/2,
push/2, and top/2 (see Appendix A).
The various System
Procedures that retrieve and update the contents of the
stack call these procedures.
Chapter 4
Rule Interpreters
There are three rule interpreters used for
proving goals.
KNAP is written entirely in Prolog, so it
uses the built-in Prolog rule interpreter both to execute
system procedures and to prove logical goals.
In logic
programming these two functions are equivalent [Lloyd,
1984].
A variant of the Prolog rule interpreter, also
implemented in Prolog, is used to prove logical goals
that may require explanations.
A third interpreter
handles the proof of askable predicates.
61
62
4.1
Prolog Rule Interpreter
The standard Prolog rule interpreter is used for
executing primitive Prolog predicates and KNAP procedures
that do not require explanations.
backward chaining
or
goal driven
Prolog employs a
control strategy.
The rule interpreter acts as a depth-first theorem
prover.
A theorem prover tries to prove a theorem P from
the axioms in the knowledge base using logical rules of
inference.
In Prolog a theorem is a goal (conjunction or
disjunction of predicates),
the axioms are the rules and
facts in the knowledge base, and the rule of inference is
top-down horn clause
modus tollens
resolution
which is equivalent to
[Kowalski, 1979].
The standard Prolog control strategy can be expressed in
a recursive pseudocode algorithm:
(* The following notation conventions are used for
*)
(* this and all subsequent pseudocode algorithms:
*)
(*
- "(*"
(*
-
(*
(*
-
. . ."*)"
denotes a comment.
*)
Identifiers that begin with upper case
*)
letters are variables.
*)
Identifiers that begin with lower case
*)
63
(*
(*
-
(*
(*
(*
letterts are constants.
*)
All parameters are passed by reference.
*)
'
-
terminates an instruction.
*)
In other cases Pascal syntax is generally
*)
followed.
*)
procedure pro prove(P, S, R)
(*
Takes a goal p and returns
(*
a substitution
(*
a Result R.
(*
If p is provable then R
(*
otherwise R
(*
function substitute(P, S)
s =
*)
{tl/vl, ••• ,tn/vn} and
*)
..--
..--
true,
takes a goal P and
(*
a substitution S
(*
returns P{tl/vl, •.• ,tn/vn}.
(*
(*
(*
*)
*)
fail.
(*
(*
*)
= {tl/vl, •.. , tn/vn} and
function head(C)
returns the head of a clause C.
function body(C)
returns the body of a clause C.
*)
*)
*)
*)
*)
*)
*)
*)
64
(*
function append(L1, L2)
*)
(*
returns the list consisting of
*)
(*
list L1 appended to the front of list L2.
*)
BEGIN
IF Pis a conjunction (P1, P2, ... , Pn) of predicates THEN
BEGIN
pro_prove(Pl, Sl, R1).
IF Rl = fail THEN
BEGIN
R := fail.
s
:=
{}
END
ELSE
BEGIN
pro prove(substitute((P2, •.. , Pn), Sl), S2, R2).
IF R2 = fail THEN
BEGIN
R := fail.
s : = (}
END
ELSE
BEGIN
R := true.
S := append(Sl, S2)
END
END
END
ELSE IF Pis a disjunction (Pl; P2; ..• ; Pn) of predicates
THEN
BEGIN
pro_prove(Pl, Sl, Rl).
IF Rl = fail THEN
pro prove((P2; ..• , Pn), S, R)
ELSE
BEGIN
R := true.
s := s1
END
END
ELSE
(* P is a single predicate *)
BEGIN
Select the first clause C from the knowledge base
such that head(C) unifies with P.
65
p •
WHILE the end of the knowledge base has not been
reached DO
BEGIN
find the unifier Sl (set of variable
substitutions) for head(C) and P.
IF C is a fact THEN
BEGIN
R := true.
S := Sl.
RETURN
END
ELSE
BEGIN
pro_prove(substitute(body(C), Sl), S2, R2).
IF R2 = fail THEN
Select the next clause C such that
head(C) unifies with P
ELSE
BEGIN
R := true.
S := append(Sl, S2).
RETURN
END
END
END.
R := fail.
s := {}
END
RETURN
END.
To prove a goal P Prolog finds a clause C whose
head unifies with P.
If C is a fact then P is proven and
the unifier for P and C is returned.
If C is a rule of
the form Pl :- Q then P can be proven if Q (with
variables bound according to the unifier of P and Pl) can
be proven.
The interpreter attempts to prove the
conjuncts of Q one at a time in a left to right ordering.
In order to prove Q the leaves of one of the paths in the
proof tree must match facts in the knowledge base.
If Q
66
cannot be proven then Prolog backtracks to another clause
whose head unifies with P and repeats the process.
If P
can be proven then the set of substitutions for variables
in P obtained on the successful path of the proof tree is
returned.
To further illustrate Prolog's proof mechanism
consider the following example knowledge base:
(El)
grandparent(X, Y)
- grandfather(X, Y).
(E2)
grandparent(X, Y) :- grandmother(X, Y).
(E3)
grandfather(X, Y)
(E4)
grandmother(X, Y) :- mother(X, Z), parent(Z, Y).
(ES)
parent(X, Y)
(E6)
parent(X, Y) :- mother(X, Y).
(E7)
father(edwin,
(ES)
mother(elaine, cynthia).
(E9)
mother(elaine, edwin).
-
father(X, Z), parent(Z, Y).
:- father(X, Y).
rosanna).
To prove the goal
(P)
grandparent(elaine, rosanna).
67
the Prolog rule interpreter proceeds as follows:
Launch (try to prove) P: find clause El whose head
1.
unifies with P.
2.
Perform the substitution {X/elaine, Y/rosanna} on
the body of El yielding the goal
Ell
3.
grandfather(elaine, rosanna).
Launch Ell: find clause E3 whose head unfies with
Ell.
4.
Perform the substitution on the body of E3
yielding
5.
E31
father(elaine, Z).
E32
parent(Z, rosanna).
Launch E31: there is no clause that unifies with
E31 so it fails, causing body of E3 to fail.
6.
Backtrack to find another clause for Ell: there is
no other clause that unifies with Ell so it fails,
causing body of El to fail.
7.
Backtrack to P: find clause E2.
68
8.
Perform subtitution on body of EZ yielding
E21
grandmother(elaine, rosanna).
9 • Launch E21: find clause E4.
10. Perform substitution on body of E4 yielding
E41
mother(elaine, Z).
E42
parent(Z, rosanna).
11. Launch E41: find clause E8.
12. E8 is a fact so E41 succeeds with Z instantiated
to "cynthia"
E41'
mother(elaine, cynthia).
13. Make the substitution for Z to E42 yielding
E42'
parent(cynthia, rosanna).
14. Launch E42': find clause ES.
15. Perform substitution on body of ES yielding
E51
father(cynthia,
rosanna).
16. Launch E51: there is no clause that unifies
with E51 so it fails,
fail.
causing body of ES to
69
17. Backtrack to E42 1
:
find clause E6.
18. Perform substitution on body of E6 yielding
E61
mother(cynthia, rosanna).
19. Launch E61: there is no clause that unifies
with E61 so it fails,
causing body of E6 to
fail.
20. Backtrack to E42 1
unifies with E42
1
:
there is no other clause that
so it fails, causing E41
1
to
fail.
21. Backtrack to E41: find clause E9.
22. E9 is a fact so E41 succeeds with Z instantiated
to "edwin"
E41
I
I
mother(elaine, edwin).
23. Make the substitution for Z to E42 yielding
E42 I
I
parent(edwin, rosanna).
24. Launch E42' ': find clause ES.
25. Perform substitution on body of ES yielding
70
ESl'
father(edwin,
rosanna).
26. Launch ESl': find clause E7.
27. E7 is a fact so ESl' succeeds.
28. Body of ES is proven (line 27) so E42'' succeeds.
29. Body of E4 is proven (lines 22, 28) so
E21 succeeds.
30. Body of E2 is proven (line 29) so P succeeds.
4.2
Explanation Rule Interpreter
Action predicates (see Chapter 5) and knowledge
base clauses are proven by a higher level Explanation
Rule Interpreter (ERI) which is executed by the Prolog
rule interpreter.
It essentially mimics the Prolog
interpreter and produces a depth-first proof tree as a
side effect as it is proving a goal.
by the predicate exprove/1.
The ERI is defined
Following is a modifcation
of the algorithm for pro_prove that describes the
71
operation of the ERI:
procedure exprove(P, S, R)
(* Takes a goal P and returns
*)
(*a substitutionS= {tl/vl, ••• ,tn/vn} and
*)
(* a Result R.
*)
(* If P is provable then R := true,
*)
(* otherwise R := fail.
*)
(* Procedure pro_prove and functions substitute, head, *)
(* body, and append are as defined previously.
*)
(* Procedure storenode(Node)
*)
(*
*)
stores a proof tree node Node in memory.
72
(l
BEGIN
IF Pis a conjunction (Pl, PZ, •.• , Pn) of predicates THEN
BEGIN
exprove(Pl, Sl, Rl).
IF Rl = fail THEN
BEGIN
R := fail.
s := {}
END
ELSE
BEGIN
exprove(substitute((PZ,
' Pn), Sl), SZ, RZ).
IF R2 = fail THEN
BEGIN
R := fail.
...
s
:= {}
END
ELSE
BEGIN
R := true.
S := append(Sl, SZ)
END
END
END
ELSE IF Pis a disjunction (Pl; PZ; •.. ; Pn) of predicates
THEN
BEGIN
exprove(Pl, Sl, Rl).
IF Rl = fail THEN
exprove((PZ; ..• ; Pn), S, R)
ELSE
BEGIN
R := true.
S : = Sl
END
END
ELSE IF P is a KNAP procedure call THEN
BEGIN
(* Do not explain KNAP procedures *)
pro prove(P, S, R).
(* Store a proof tree node that tells *)
(* the result of pro prove.
*)
IF R = fail THEN
storenode(failed(P))
ELSE
BEGIN
PZ := substitute(P, S).
storenode((PZ <- true))
END
END
•
73
ELSE IF P is a KNAP system predicate THEN
(* System predicates are hidden from the user *)
·
(* Do not store a proof tree node for P
*)
pro prove(P, S, R)
ELSE IF P = askable(Pl) THEN
(* Pl is an Askable Predicate
*)
(* Call the Consultation Mode Interpreter *)
askable(Pl, S, R)
ELSE
(* P is a single predicate *)
BEGIN
Select the first clause C from the knowledge base
such that head(C) unifies with P.
WHILE the end of the knowledge base has not been
reached DO
BEGIN
find the unifier Sl (set of variable
substitutions) for head(C) and P.
Pl := substitute(P, Sl).
CBody := body(C).
(* Store a node representing the rule C *)
storenode((Pl <- CBody)).
IF C is a fact THEN
BEGIN
R := true.
S := Sl.
RETURN
END
ELSE
BEGIN
pro prove(substitute(CBody, Sl), S2, R2).
IF R2 = fail THEN
BEGIN
Select the next clause Cl such that
head(Cl) unifies with P.
C := Cl
END
ELSE
BEGIN
R := true.
S := append(Sl, S2).
P2 := substitute(P, append(Sl, S2)).
(* Store a proof tree node that *)
(* says P2 been proven.
*)
storenode(P2 <-true).
RETURN
END
END
END.
R := fail.
74
s
:= {}.
(* Store a proof tree node that says that P failed *)
storenode(failed(P))
END
RETURN
END.
Procedure storenode can be defined in prolog:
storenode(Node)
:-
assert(pt(Node)).
where pt/1 is simply a label that marks Node as a proof
tree node.
After exprove exits from proving a goal the
user may enter the commands "why" or "explain".
Either
of these commands calls the KNAP procedure explain/0
which retrieves the proof tree nodes, translates them
into English, and displays them to the user in the order
in which they were stored (see Appendix B for a
transcript of an explanation).
Thus the user is shown a
trace of the depth-first search that led to the proof or
failure of the most recent goal.
This use of a trace of program execution to
explain system conclusions has been succesfully used by
TEIRESIAS [Davis, 1982], a front-end for MYCIN.
All
proof tree nodes are deleted prior to the beginning of a
proof so only the most recent proof tree is available at
75
any given time.
4.3
Consultation Mode Interpreter
Sometimes a goal concerning Situation Model
information may not be provable from the knowledge base
but the user may know the information.
For example, the
fact that a new motion has been seconded may not be in
the knowledge base but the user might know this fact.
such cases
askable predicates
are used.
In
An askable
predicate is a goal whose truth value can be determined
dynamically (as the goal is being proven) by the user, if
it is not provable from the knowledge base.
''negation as failure" is not adhered to.
In this case
MYCIN uses a
similar technique to obtain evidence from the user when
it is not derivable from the knowledge base.
An askable predicate has the form
askable(P).
When the Explanation Rule Interpreter encounters this
type of goal it calls the Consultation Mode Interpreter
76
(CMI) on P.
The CMI first tries to prove P by calling
exprove(P)
If this fails then P is negated and exprove/1 of the
negation is attempted.
Negation of a goal is defined in
the KNAP procedure negate/2 as:
negate(not Goal, Goal) :- !.
negate(false Goal, Goal)
:- !.
negate(Goal, false(Goal)).
where the first argument is the input goal and the second
argument is its negation.
In practice the second clause
is never used for askable predicates since a false(P)
goal never appears as an askable predicate in KNAP.
If
the negation is provable then the original goal P fails.
If the proof of the negation fails then the user is asked
whether or not P is true.
If the user answers positively
then P is added as a fact to the Situation Model.
Otherwise the negation of P is added to the Situaton
Model (thus ensuring that P will not be asked about in
the future).
askable/1.
CMI:
The CMI is defined by the predicate
Following is a pseudocode algorithm for the
77
procedure askable(P, S, R)
(*
Takes a goal p and returns
(*
a substitution
(*
Result R.
(*
If p is provable then R
(*
otherwise R
(*
Procedure negate(G, NegG)
s =
*)
{tl/vl, .•• ,tn/vn} and a
*)
*)
..--
..--
true,
fail.
*)
*)
*)
(*
takes a goal G and returns its negation NegG
*)
(*
using false/! when necessary.
*)
78
BEGIN
exprove(P, Sl, Rl).
IF Rl = f~il THEN
BEGIN.
negate(P, NegP).
exprove(NegP, NSl, NRl).
IF NRl = fail THEN
BEGIN
ask the user if P is true.
IF the user says "Yes" THEN
BEGIN
add the fact P to the knowledge base
R := true.
s := {}
END
ELSE
BEGIN
add the fact NegP to the knowledge base.
R := fail.
s
:=
{}.
END
END
ELSE
(* Negation of P is true so fail *)
BEGIN
R := fail.
s : = {}
END
END
ELSE
(* P is true
BEGIN
R := true.
S : = Sl
END
*)
END.
As an example take the goal
(1)
askable(seconded(l4:main)).
This is a call to the CMI to prove the goal "motion
14:main has been seconded".
If this goal is provable
79
il
then (1) succeeds.
Otherwise the CMI tries to prove the
negation:
(2)
false(seconded(ID:RNum)).
If (2) is provable then (1) fails.
Otherwise it
translates
(3)
seconded(ID:RNum).
into English and asks the user:
Is it true that:
motion 14:main has been seconded?
[yes.
I
no.]
>
If the user answers ''yes" then (1) succeeds and (3) is
added to the Situation Model.
Otherwise (1) fails and
(2) is added to the Situation Model.
•
80
4.4
Default Reasoning
Some rules in RROO are stated in terms of their
exceptions.
For example, the rule that determines
whether a motion to Appeal is debatable is stated as:
••• it is debatable except when it
relates to indecorum, or transgression of
the rules of speaking, or to the priority
of business, or when it is made during a
division of the assembly, or while an
undebatable question is pending.
Rules like this state that a motion possesses a
particular attribute ("debatability'' in this case) by
default , unless certain other conditions are true.
define such rules in the Domain Model, a form of
reasoning
is used [Reiter, 1978].
Default rules
To
default
have
the form
<Goal> :- not false( <Goal> ).
A default rule states that <Goal> is true if the explicit
negation false( <Goal> ) is not provable.
A rule with
head false( <Goal> ) defines an exception to the default
rule:
false( <Goal> ) :- <Condition).
81
So the rule governing the debatability of a
motion to Appeal is expressed in the Domain Model as:
debatable(ID:r21a) :not false(debatable(ID:r21a).
false(debatable(ID:r2la) :relates_to(ID:r21a, indecorum).
false(debatable(ID:r21a) :relates_to(ID:r21a, 'rules of speaking').
false(debatable(ID:r2la) :relates_to(ID:r21a, 'priority of business').
false(debatable(ID:r2la) :/* See if a motion for Division of the Assembly */
I* has been made.
*I
log(resolved(ID2:r25, ApplyTo, passed), Time),
/*If so, see if the motion it applies to is active.*/
order(ApplyTo, active).
false(debatable(ID:r21a) :/* See if any undebatable motions are pending */
order(Motion, pending),
not debatable(Motion).
(the identifier r21a is the rule number for a Motion to
Appeal and ID is the unique id of the Motion to Appeal).
Thus any Motion to Appeal is debatable unless one of the
false-debatable rules for Appeal is provable.
Chapter 5
Input Processing
When displaying the top level prompt "READY>"
There are three types of input that KNAP recognizes:
1.
Actions (State Updates)
2.
Queries
3.
Commands
All valid inputs are Prolog predicates aE specified
below.
82
83
5.1
User Interface
The User Interface (UI) is a simple command
interpreter that accepts input from the user and executes
it.
The UI is activated immediately when KNAP is
started.
It is defined by the predicates
process_input/1, process_input1/1, and process update/1.
An input P is valid if it unifies with the argument of
one of the process input1/1 clauses for queries or if
either
valid_command(P)
(for KNAP and Prolog system predicates) or
valid_action(P)
(for state updates)- succeeds.
rejected with an error message.
All other inputs are
84
5.2
Actions
An action is an update to the internal state
representation. To perform an action the user inputs an
action predicate
the assembly.
that corresponds to the action made by
For each action predicate there is a
defining rule in the Domain Model (DM) with the action
predicate as head.
The UI determines the legality of an
action predicate AP (according to RROO) by calling
exprove(AP).
The action predicate rules of the DM are partly
declarative and partly procedural in nature in that they
specify the conditions that are necessary for an action
to be legal but they also cause side effects.
The period of time from the moving of a motion to
its resolution is divided into four "assembly states":
1)
"considering_motion"
2)
"debate" or "resolving_motion" (for non-debatable
motions)
3)
"put question"
4)
"voting" or "resolved" (for motions decided by
85
the chair)
The action predicate rules define a finite state machine.
Actions cause state changes and only certain actions are
acceptable in any particular state.
For example, it is
legal to state a motion to the assembly only when the
assembly_state is "considering_motion" (meaning that the
motion is in order), and this action changes the
assembly_state to either "debate" or "resolving_motion".
Below are the valid action predicates.
"Action"
is the action predicate, "Meaning" is its meaning in
English, "Preconditions" are the conditions that must be
true for the action to be legal, and "Postconditions" are
what happen if the action is legal:
Action:
M obtains.
Meaning:
Member M attempts to obtain the floor.
Preconditions:
No one has the floor or M wants
to make a motion that may interrupt a member who
already has the floor.
Postconditions:
If no other member has the floor
86
Q .
then the has-floor entry of the active context
tuple is updated to M.
If'M is making a motion
then call make_motion(M).
Action:
M yields.
Meaning:
Member M yields the floor.
Preconditions:
Postconditions:
Member M has the floor.
The has-floor entry of the
active context tuple is changed to null.
Action:
M makes RNum.
Meaning: Member M makes a motion of type RNum,
where RNum is a KNAP rule number.
Preconditions:
The motion that M is making is in
order.
Postconditions:
motion.
KNAP generates a new ID for the
A new context tuple is added to the
pending stack, the assembly_state is changed to
87
considering_motion, history is updated.
Action:
state X.
Meaning: The Chairman states motion X to the
assembly, where X is an ID:RNum pair.
Preconditions:
X is currently active, the
assembly_state is considering_motion.
Postconditions:
The assembly_state is changed to
either debate or resolving motion (if X is not
debatable), history is updated.
Action:
M debates X.
Meaning: Member M debates motion X.
Preconditions:
X is currently active, X is
debatable, the assembly_state is debate, M has
the floor.
Postconditions:
History is updated.
88
Action:
put X.
Meaning: The Chairman puts motion X to the
assembly for vote.
Preconditions:
the floor,
X is currently active, no one has
the assembly_state is either debate or
resolving_motion.
Postconditions:
The assembly_state is changed to
put question, history is updated.
Action:
vote X.
Meaning: The members vote on motion X.
Preconditions:
X is currently active, X has not
been previously voted on, a division of the
assembly has not been called for,
the assembly
state is put_question.
Postconditions:
assembly_state is changed to
voting, KNAP asks for the vote count and
calculates the result, history is updated.
89
Action:
vote_by_division X
Meaning: The members vote by division of the
assembly on motion X.
Preconditions:
X is
currentl~
active, a division
of the assembly has been called for,
the assembly
state is either put_question or voting.
Postconditions:
assembly_state is changed to
voting, KNAP asks for the vote count and
calculates the result, history is updated.
Action:
resolve X.
Meaning: The Chairman makes a decision on motion
X.
Preconditions:
X is currently active, X is
decidable by the Chair, the assembly_state is
either considering_motion, debate, or
resolving_motion.
90
Postconditions:
KNAP asks for the Chairman's
decision, history is updated.
Action:
dispose X.
Meaning: Motion X is disposed of by being carried
out or removed from consideration.
Preconditions:
X is currently active, the
assembly has voted on X or the Chairman has
decided X.
Postconditions:
The active context tuple is
popped off the pending stack.
Any State Model
changes that are necessary to carry out motion X
are performed.
Below is an annotated transcript of an actual
KNAP session with input based on the hypothetical session
given in Chapter 1.
The actions of the assembly, taken
from Chapter 1, appear inside braces.
Immediately
following the actions are the KNAP inputs corresponding
to those actions.
91
K N A P
THE KNOWLEDGE BASED AUTOMATED PARLIAMENTARIAN
{Member #18 obtains the floor.}
READY>
member18 obtains.
Action accepted
{Member #18 makes a Main Motion (ID #1):
"To halt deployment of nuclear weapons in Europe."
Member #24 seconds the Motion.}
READY>
member18 makes main.
The ID for this new motion is 1
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n') > n
Is it true that
motion 1:main has been seconded?
[yes. I no. ] > y
Action accepted
{The Chair rules motion #1 to be in order.
The Chair states motion #1 to the assembly.}
READY>
state 1:main.
Action accepted
{member #15 makes an Incidental Motion (ID #2):
92
Objection to Consideration of the Question.}
READY>
member15 makes r23.
The ID for this new motion is 2
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n') > 1
Action accepted
{The Chair rules motion #2 to be in order.
The Chair states motion #2 to the assembly.}
READY>
state 2:r23.
Action accepted
{Member 15 yields the floor.}
READY>
member15 yields.
Action accepted
{The Chair puts motion #2 to the assembly for vote
(motion #2 is not debatable).}
READY>
put 2:r23.
Action accepted
{The assembly votes to defeat motion #2.}
READY>
vote 2:r23.
Enter the number of votes in favor of motion 2:r23
>
2
Enter the number of votes against motion 2:r23
93
>
8
Enter the number of abstentions
>
0
The result of the vote on motion 2:r23 applied to motion
1:main : failed
Action accepted
READY>
Done
dispose 2:r23.
The current state is debate
Motion 1:main is currently active
No one has the floor
Action accepted
{Member #12 obtains the floor and states her opinion
on motion #1.}
READY>
member12 obtains.
Action accepted
READY>
member12 debates l:main.
Action accepted
{Member #9 makes a Subsidiary Motion (ID #3):
To Postpone motion #1 to a set time.}
READY>
member9 makes r31.
The ID for this new motion is 3
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n') > 1
94
ILLEGAL ACTION
it is
it is
it is
which
it is
false that
false that
false that
applies to
false that
member
motion
member
motion
member
member9 has
3:r31 is in
member9 may
1:main
member9 may
the floor
order
make motion 3:r31
make a motion
{The Chair rules that member #9 is out of order
because a Motion to Postpone to a set time cannot
interrupt a speaker who has the floor.
Member #12 concludes her remarks and relinquishes
the floor.}
READY>
member12 yields.
Action accepted
{Member #33 obtains the floor and makes a Subsidiary
Motion (ID #4): To Amend motion #1 to read:
"To advise the President to halt deployment of
nuclear weapons in Europe."
Member #19 seconds the motion.}
READY>
member33 obtains.
Action accepted
READY>
member33 makes r33.
The ID for this new motion is 4
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n') > 1
Is it.true that
motion 4:r33 has been seconded?
[yes. I no.] > y
Action accepted
95
{The Chair rules motion #4 to be in order.
The Chair states motion #4 to the assembly.}
READY>
state 4:r33.
Action accepted
{Member #33 states his opinion on motion #4 and
relinquishes the floor.}
READY>
member33 debates 4:r33.
Action accept_ed
READY>
member33 yields.
Action accepted
{Member #12 obtains the floor and makes a Subsidiary
Motion (ID #5): To Limit Debate on motion #4 to
1 hour.
Member #26 seconds the motion.}
READY>
member12 obtains.
Action accepted
READY>
member12 makes r30.
The ID for this new motion is 5
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n') > 4
Is it true that
motion 5:r30 has been seconded?
[yes. I no.]> y
Action accepted
96
{The Chair rules motion #5 to be in order.
Member 12 yields the floor.}
READY>
member12 yields.
Action accepted
{The Chair states motion #5 to the assembly.}
READY>
state 5:r30.
Action accepted
{The Chair puts motion #5 to the assembly for vote
(motion #5 is not debatable).}
READY>
put 5:r30.
Action accepted
{The assembly votes in favor of motion #5.}
READY>
vote 5:r30.
Enter the number of votes in favor of motion 5:r30
>8
Enter the number of votes against motion 5:r30
>1
Enter the number of abstentions
>1
The result of the vote on motion 5:r30 applied to motion
4:r33 : passed
Action accepted
97
READY>
Done
dispose S:r30.
The current state is debate
Motion 4:r33 is currently active
No one has the floor
Action accepted
{Member #49 obtains the floor and makes a Subsidiary
Motion (ID #6): To Postpone motion #1 Indefinitely.}
READY>
member49 obtains.
Action accepted
READY>
member49 makes r34.
The ID for this new motion is 6
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n') > 1
ILLEGAL ACTION
there
it is
it is
which
it is
is a subsidiary motion pending
false that motion 6:r34 is in order
false that member member49 may make motion 6:r34
applies to motion l:main
false that member member49 may make a motion
{The Chair rules motion #6 to be out of order because
a motion with higher precedence (motion #4) is under
is under consideration.
Member49 yields the floor.}
READY>
member49 yields.
Action accepted
:70
{Member #56 obtains the floor and makes a Subsidiary
Motion (ID #7): To Refer motion #1 to a Committee.
Member #44 seconds the motion.}
READY>
member56 obtains.
Action accepted
READY>
member56 makes r32.
The ID for this new motion is 7
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n') > 1
Is it true that
motion 7:r32 has been seconded?
[yes. I no.]> y
Action accepted
{The Chair rules motion #7 to be in order.
Member 56 yields the floor.}
READY>
member56 yields.
Action accepted
{The Chair states motion #7 to the assembly.}
READY>
state 7:r32.
Action a cepted
{The: Chair puts motion #7 to the assembly for vote
il
99
(motion #7 is not debatable).}
READY>
put 7:r32.
Action accepted
{The assembly votes in favor of motion #7.}
READY>
vote 7:r32.
Enter the number of votes in favor of motion 7:r32
> 7
Enter the number of votes against motion 7:r32
>3
Enter the number of abstentions
>
0
The result of the vote on motion 7:r32 applied to motion
l:main : passed
Action accepted
{Motion #1 and its adhering motion #4 are referred to
a committee.}
READY>
dispose 7:r32.
To what committee will the motion be referred?
enter a unique ID > pussyfooters.
Done
There are no motions currently pending
Action accepted
READY>
halt.
KNAP Session Completed
'
100
5.3
Queries
The user may ask queries of the system in the
form of Prolog goals.
There are two kinds of queries:
1.
Yes/No queries.
2.
WH (who, what, when, where) queries.
5.3.1
Yes/No Queries
Yes/No queries are questions that ask whether a
particular Prolog goal is provable from the knowledge
base.
These queries have the form
q(Goal).
where Goal is a Prolog goal.
The UI answers Yes/No
queries by calling the Prolog system predicate
call( Goal)
101
If Goal is provable the UI answers "Yes."
Otherwise the
convention of "negation as failure" is followed and the
UI answers "No."
5.3.2
WH Queries.
WH queries are questions that ask for all
possible instantiations of one or more variables that
make a given Prolog goal true.
These queries have the
form
q(VarList, Goal).
where VarList is a Prolog list of variables and Goal is a
Prolog goal in which the variables from VarList are
mentioned.
For example, if the user wanted to know the
identifiers of all motions that are currently pending
s/he could ask the WH query
q([X], order(X, pending)).
This tells KNAP to find all instantiations of the
variable X that make order(X, pending) true.
To do this
102
the UI simply calls the Prolog system meta-predicate
findall/3
findall([X],
5.4
order(X, pending), Answers).
Commands
There are two kinds of commands that the UI will
execute:
1.
KNAP system commands.
2.
Primitive Prolog system predicates.
Following is a list of KNAP system commands:
Command:
explain.
Result:
KNAP displays the proof tree that led
to the proof or failure of the most recent State
Update.
Command:
halt.
103
Result:
The session is ended, minutes/0 is
called, and KNAP execution is terminated.
Command:
minutes.
Result:
All log predicates for the session
(translated into English) are listed in order of
their occurrence.
pending.
Command:
Result:
Displays the contents of the pending
stack in order of precedence.
Command:
show.
Result:
Displays the following menu:
1.
Domain Facts
2.
Domain Rules
3.
Domain Predicate
4.
Domain Predicate Names
5.
Rule Numbers
The user may select one of these categories and
it will be displayed.
104
Command:
what now.
Result:
Displays the active (immediately
pending) context tuple (State, Motion, Has-floor)
and a list of possible State Updates that may be
attempted at that time.
Command:
why.
Result:
Same as for "explain."
The UI executes a KNAP system command (with the exception
of "halt") by calling the System Procedure of the same
name.
For example, to execute the command "explain" the
UI calls the System Procedure explain/0.
In addition the user may enter any Prolog system
predicate (e.g., listing/1, break/0, save/1) and the UI
will execute it by calling the Prolog system predicate of
the same name.
Chapter 6
Concluding Remarks
KNAP demonstrates that logic programming
techniques can be used to represent a legal system of
rules within the context of a knowledge-based system.
KNAP has most of the features necessary for a complete
expert system,
including a consultation mode (using the
Consultation Mode Interpreter), full explanations to
justify both successful and unsuccessful proofs, an
efficient inferencing mechanism, and a declarative
knowledge base.
It does not have any inexact reasoning
capability because inexact reasoning is irrelevant to
RROO, which requires that all facts be completely
certain.
The Domain Model facts and rules are taken from
Henry Robert's
mo~t
Robert's Rules of Order, Revised , the
authoritative guide for parliamentary law.
Since
KNAP's inference mechanism is essentially that of Prolog
it should be as sound and complete as horn clause
resolution.
Thus the only possible source of error in
105
106
the Domain Model is the programmer's translation of the
rules from English to PKRL.
Since PKRL is an extension
of Prolog, which is well suited to the declarative
representation of logical clauses, these errors have
hopefully been kept to a minimum.
Th~
Domain Model is a modular body of knowledge.
New rules can be easily added or existing rules modified
without affecting the System Procedures or rule
interpreters.
For example, if a new motion type were
invented it could be implemented by simply adding a few
new rules to the DM.
Thus the expansion and maintenance
of the Domain Model is a relatively easy task.
KNAP' s weakest area' is user interaction.
User Interface accepts only Prolog predicates.
The
A simple
Prolog DCG parser would remedy this deficiency by
accepting strings of words instead of predicates.
A more
flexible natural language front end could also be
implemented on top of KNAP.
Alternatively a new type of
"shorthand" input language could be developed similar to
that used by court recorders.
English output to the user also has limitations.
Although explanations consist of approximate English
translations of Prolog clauses, they are somewhat stilted
107
and unnatural.
The proof trees shown in explanations
might be clearer to the user if they went through a more
general PKRL-to-English translator.
The same is true of
questions arising from askable predicates that are asked
of the user.
The Consultation Mode Interpreter should be
modified to answer "why" (''why do you want to know
that?") questions.
This would enable the user to ask the
system why a particular askable predicate was being asked
about.
To answer such a question the CMI could display a
translation of the current rule in whose antecedent the
askable predicate occurs.
The user could then ask "why''
again to determine why the consequent of that rule is
important, and this process could continue back to the
original top level Action Predicate goal.
TEIRESIAS
handles this kind of "why" question in a similar way.
Currently the only way that the knowledge base
can be altered is by breaking to Prolog and direcly
retracting and asserting PKRL clauses.
A new interface
could be created to simplify editing of the knowledge
base,
(especially the context stack) should the user
wish,
for example, to manually alter the order of
consideration of pending motions.
In general KNAP's
processing of State Updates could be made more flexible
108
to allow the system's decisions to be more easily
overidden by the Chairman.
Overall KNAP has the ability to function
reasonably well as an automated parliamentarian.
Although written in Prolog and executed interpretively,
it provides fast interactive responses to updates,
commands, and queries.
It does not maintain any detailed
information about the content of motions, but such
information is not necessary to resolve questions of
parliamentary procedure.
The system cannot replace the
Chairman of a deliberative assembly.
However, it can
probably replace the parliamentarian of an assembly,
especially if the above recommendations are followed.
109
References
Buchanan, B.G., and E.A. Feigenbaum, 1978.
"DENDRAL and
Meta-DENDRAL: Their Applications Dimension",
Artificial Intelligence, Vol. 11, pp. 5-24.
Clocksin, W.F, and C.S. Mellish, 1981.
Prolog , Springer-Verlag, Berlin.
Programming in
Davis, R., 1982.
"Applications of Meta Level Knowledge
to the Construction, Maintenance and Use of Large
Knowledge Bases", in Knowledge-based Systems in
Artificial Intelligence , R. Davis and D.B. Lenat
(Eds.), McGraw-Hill, New York.
Duda, R.O., J.G. Gaschnig, and P.E. Hart, 1979. "Model
Design in the PROSPECTOR consultant system for
mineral exploration", in Expert Systems in the
Micro-electronic Age , D. Michie (Ed.), Edinburgh
University Press, Edinburgh, pp. 153-167.
Frisch, A.M., 1985.
"An Investigation into Inference
with Restricted Quantification and a Taxonomic
Representation", Sigart Newsletter, No. 91, pp.
28-31.
Hayes-Roth, F., D.A. Waterman, and D.B. Lenat (Eds.),
1983.
Building Expert Systems , Addison-Wesley,
Reading, Mass., pp. 13-16.
Kowalski, R., 1979.
Logic for Problem Solving , North
Holland, New York, pp. 55-57.
Lloyd, J.W., 1984.
Foundations of Logic Programming ,
Springer-Verlag, Berlin, pp. 1-4.
McDermott, J., 1982.
"R1: A Rule-based Configurer of
Computer Systems", Artificial Intelligence, Vol. 19,
pp. 39-88.
Martin, W.A., and R.J. Fateman, 1971.
"The MACSYMA
system", in Proceedings of the Second Symposium on
Symbolic and Algebraic Manipulation, Los Angeles, pp.
59-75.
Nilsson, N.J., 1980.
Principles of Artificial
Intelligence , Tioga Pub. Co., Palo Alto, pp. 145-49.
Peterson, J., and A. Silberschatz, 1983.
Operating
110
System Concepts , Addison-Wesley, Reading, Mass., pp.
112-113.
Reiter, R., 1978.
"On Reasoning by Default", in
Proceedings of TINLAP-2: Theoretical Issues in
Natural Language Processing.
Robert, H.M., 1979.
Robert's Rules of Order, Revised ,
Morrow Quill Paperbacks, New York.
Shortliffe, E.H., 1976. Computer-based Medical
Consultation: MYCIN , American Elsevier, New 'York.
Stefik, M., 1981a.
"Planning with Constraints (MOLGEN:
Part 1)", Artificial Intelligence, Vol. 16, pp.
111-139.
Stefik, M., 1981b.
"Planning and Meta-planning (MOLGEN:
Part 2)", Artificial Intelligence, Vol. 16, pp.
141-169.
Ullman, J.D., 1980.
Principles of Database Systems ,
Computer Science Press Inc., Potomac, Maryland, pp.
10-17.
111
Appendix A
Code Listing
Predicates are listed alphabetically within each file,
unless otherwise indicated. Below is an index to all KN AP predicates:
Index to KN AP Predicates
Predicate N arne
File Name
File Page Number
add_pending_motion/2
adheres to/2
amendable/1
append_to_file/2
applicable_to/2
askable/1
ask about motion/3
ask_about_qop/1
assembly_state/1
business since last moved/1
business transacted/2
carry_out/3
class status/2
conditionaV3
copy_term/2
debatable/1
debates/2
decidable_by_chair/ 1
dispose/1
domain head/1
eligible_for_consideration/2
eligible_for_consideration/4
even/1
exit...:..message/0
explain/0
explain/2
exprove/1
extract_adhering_motions/3
has jfloor/1
initihlize/0
in drder/3
inpJt_decision/2
invmid_input/2
code.pl
code. pi
rules.pl
io.pl
rules.pl
interp.pl
code.pl
code.pl
cxtpl
code. pi
code.pl
code.pl
code.pl
code. pi
interp.pl
rules.pl
action.pl
rules.pl
action.pl
rules.pl
rules.pl
rules.pl
code. pi
top.pl
explain.pl
explain. pi
interp.pl
code. pi
cxtpl
com.pl
rules.pl
code. pi
code. pi
141
141
119
171
119
134
141
141
162
141
141
141
141
141
134
119
114
119
114
119
119
119
141
137
166
166
134
141
162
156
119
141
141
112
knap/0
knap_predicate/ 1
list_conjunction/2
list_disjunction/2
mak.es/2
mak.es/3
making_motion/2
may_have_floor/1
minutes/0
motion class/2
needed_to_pass/2
negate/2
numberedvar/1
obtains/!
order/2
orderly_introduction/!
output/!
padding_needed/3
pending/0
pop/2
precedences/!
procedure/ 1
process_input/1
process_inputl/1
process_update/1
prolog_to_english/2
prompt_cycle/2
p_to_e/2
push/2
putq/1
read and echo/1
read_input/1
remove_knap_predicates/2
resolve/1
rule number/2
script/1
set difference/3
show/0
startup_message/0
state/1
storenode/ 1
time_sequence/1
top/2
translate_and_negate/2
translog/3
update_floor/1
update_pending/2
update_state/1
top.pl
explain. pi
explain. pi
explain.pl
action.pi
action.pi
code. pi
rules.pl
com. pi
rules.pl
rules.pl
code. pi
translate.pi
action.pl
cxt.pl
rules.pl
io.pl
code. pi
com.pl
cxt.pl
rules.pl
explain. pi
top.pl
top.pl
top.pl
translate.pi
io.pl
translate.pl
ext. pi
action.pl
io.pl
top. pi
explain.pl
action.pl
rules.pl
com. pi
code. pi
com. pi
top.pl
action.pl
interp.pl
code. pi
cxt.pl
translate.pi
translate.pl
cxt.pl
ext. pi
cxt.pl
137
166
166
166
114
114
141
119
156
119
119
141
174
114
162
119
171
141
156
162
119
166
137
137
137
174
171
174
162
114
171
137
166
114
119
156
141
156
137
114
134
141
162
174
174
162
162
162
0 •
113
% file name:
% purpose:
operators. pi
Operator definitions for KNAP.
:- op(950, fy, [false, listing, save, trace]).
% The list functor.
:- op(600, xfy, '.').
% Operator for X:T notation.
:- op(350, xfy, ':').
% Operators for action predicates.
:- op(950, fx, [state, put, resolve, vote, vote_by_division, dispose, script]).
:- op(950, xf, [obtains, yields]).
:- op(950, xfx, [makes, debates]).
114
%file name:
%purpose:
%module:
action.pl
Action Predicates for user update of state.
DM
% *************************************************************************
% DEBA1ES
% A member debates a motion.
debates(MemiD, Motion) :order(Motion, active),
once(debatable(Motion)),
assembly_state(debate),
has_floor(MemiD),
time_sequence(Tag),
assert(log(event(debated, MemiD, Motion), Tag)).
% *************************************************************************
% DISPOSE
% Dispose of a motion that has been resolved.
dispose(Motion) :order(Motion, active),
tentative_result(Motion, ApplyTo, Result),
retract( tentative_result(Motion, ApplyTo, Result)),
retractall(division_called_for(Motion)),
time_sequence(Tag),
assert(log(resol ved(Motion,ApplyTo,Result), Tag)),
% Update the KB.
carry_out(Motion, ApplyTo, Result),
output((nl, write('Done'))),
% Tell user the current context.
top(pending, NewContext),
inform(currently_active, NewContext).
% *************************************************************************
%MAKES
% A member makes a motion type (rule number).
% User's top level mak:es/2.
makes(MemiD, RNum) :% Generate a unique motion ID and find out which
115
% motion RNum applies to (if any).
ask_about_motion(RNum, Motion, ApplyTo),
time_sequence(Tag),
assert(log(event(made_motion, MemiD, Motion), Tag)),
makes(MemiD, Motion, ApplyTo).
% makes/3 for Raising Question of Privilege (non-motion).
makes(MemiD, MID:r19, ApplyTo) :% Ask the user if s/he wants to make a formal motion.
% If so then fail and go to default rule below.
ask_about_qop(MemiD),
once(in_order(MID:r19a, MemiD, ApplyTo) ),
time_sequence(Tag),
assert(log(event(in_order, MID:r19a), Tag)),
assert( applies_to(MID:r19a, ApplyTo)),
add_pending_motion(MemiD, MID:r19a),
resolve(MID:r19a).
% makes/3 for Division of Assembly.
makes(MemiD, MID:r25div, ApplyTo) :once(in_order(MID:r25div, MemiD, ApplyTo)),
time_sequence(Tag),
assert(log(event(in_order, MID:r25div), Tag)),
assert( applies_to(MID:r25div, ApplyTo) ),
% Add a flag to the state model.
assert(division_called_for(ApplyTo)).
% . Default makes/3 for all other motions.
makes(MemiD, Motion, ApplyTo) :once(in_order(Motion, MemiD, ApplyTo)),
time_sequence(Tag),
assert(log(event(in_order, Motion), Tag)),
assert( applies_to(Motion, Appl yTo) ),
add_pending_motion(MemiD, Motion).
% *************************************************************************
% OBTAINS
% A member obtains the floor.
% If no one has the floor then legal.
obtains(MemiD) :not has_floor(_),
update_fioor(MemiD),
time_sequence(Tag),
assert(log(event(obtained_floor, MemiD), Tag)).
116
% Member already has the floor.
obtains(MemiD) :has_floor(MemiD),
output((nl,nl, write('Member '), write(MemiD),
write(' already has the floor.'))).
% If someone has the floor see if MemiD is making a motion that can
% interrupt a speaker.
obtains(MemiD) :making_motion(MemiD, RNum),
makes(MemiD, RNum).
9.0 *************************************************************************
9.0 PUTQ
· % A motion is put to the assembly for vote.
putq(Motion) :order(Motion, active),
9.0 Make sure nobody has the floor.
not has_floor(_),
(assembly_state(debate); assembly_state(resolving_motion)),
update_state(put_question),
time_sequence(Tag),
assert(log(event(put_question, Motion), Tag)).
% *************************************************************************
9.0 RESOLVE
9.0 The Chair resolves a motion.
resolve(Motion) :order(Motion, active),
decidable_by_chair(Motion),
once((assembly_state( considering_motion);
assembly_state( debate);
assembly_state(resolving_motion))),
update state(resolved),
update floor(#),
% Ask for the Chair's decision.
input_decision(Motion, Result),
applies_to(Motion, ApplyTo ),
assert( tentative_result(Motion, ApplyTo, Result)),
assert(decided(chair, Motion)).
117
9& *************************************************************************
9& STATE
9& State a motion to the assembly.
state(Motion) :order(Motion, active),
assembly_state(considering_motion),
%If the motion is debatable then change the assembly_state to "debate",
% otherwise change it to "resolving_motion".
conditional(debatable(Motion),
update_state(debate),
update_state(resolving_motion)),
time_sequence(Tag),
assert(log(event(stated, Motion), Tag)).
9& *************************************************************************
9& VOTE
9& Vote on a motion.
vote(Motion) :order(Motion, active),
%Make sure Motion hasn't been voted on already.
not tentative_result(Motion, _, _),
9& If a division of assembly was called for then this is not legal.
not division_called_for(Motion),
assembly_state(put_question),
update_state( voting),
vote_on(Motion).
% *************************************************************************
9& VOTE BY DIVISION
% Vote on a motion by division of the assembly.
vote_by_division(Motion) :order(Motion, active),
division_called_for(Motion),
(assembly_state(put_question); assembly_state( voting)),
update_state( voting),
vote_on(Motion).
118
9& *************************************************************************
% YIELDS
% A member yields the floor.
yields(MemiD) :has_floor(MemiD),
% Replace MemiD with the null (#) symbol.
update_floor(#).
119
% file name:
% purpose:
% module:
rules.pl
KNAP Domain Model
DM
% *************************************************************************
% AMENDABLE
amendable(_:rl6).
amendable(_:r18).
amendable(_:rl9).
amendable(_:r24).
amendable(_:r25).
amendable(_:r26close).
amendable(_:r26reop).
amendable(_:r30).
amendable(_:r31 ).
amendable(_:r32).
amendable(MID:r33) :not (applies_to(AID:r33, MID:r33), order(AID:r33, pending)),
%Make sure MID:r33 is not concerned with filling blanks.
not askable(relates_to(MID:r33, ['filling blanks'])).
amendable(Motion) :motion_class(Motion, main),
not (applies_to(AID:r33, Motion), order(AID:r33, pending)).
% *************************************************************************
% APPLICABLE TO
%Appeal
applicable_to(MID:r21a, ApplyTo) :decided(chair, ApplyTo),
%Find time when MID:r21a was made.
log(event(made_motion, _, MID:r2la), TU),
% Find time when ApplyTo was resolved.
log(resolved(ApplyTo, _, _), TL),
% If no business has occurred between TL and TU then OK.
not business_transacted(TL, TU).
% Objection to Consideration of a Question
applicable_to(_:r23, ApplyTo) :motion_class(ApplyTo, main).
% Division of Assembly
applicable_to(_:r25div, ApplyTo) :-
Q '
120
askable(voting_method(ApplyTo, viva_voce)).
applicable_to(_:r25div, ApplyTo) :not voting_method(ApplyTo, viva_voce),
askable(voting_method(ApplyTo, show_of_hands)).
% Lay on the Table
% applied to Main motion.
applicable_to(MID:r28, ApplyiD:ApplyNum) :motion_class(ApplyiD:ApplyNum, main),
ApplyNum\= r35,
!.
% applied to Question of Privilege
applicable_to(MID:r28, ApplyiD:r19) :% Make sure no other privileged motions are pending.
forall((order(PID:PNum, pending), motion_class(PNum, privileged)),
PID = ApplyiD),
!.
% applied to order of the day.
applicable_to(MID:r28, ApplyTo) :% See if ApplyTo is an Order of the Day.
order_of_the_day(Orders, _),
member(context(_, ApplyTo, _),Orders),
!.
% applied to Appeal
applicable_to(MID:r28, _:r2la).
% applied to Reconsider
applicable_to(MID:r28, ApplyiD:r36) :order(ApplyiD:r36, active),
!.
% Previous Question
applicable_to(_:r29, ApplyTo) :once(debatable(ApplyTo)),
!.
applicable _to(_:r29, ApplyTo) :amendable(ApplyTo),
!.
% Commit
applicable_to(_:r32, _:ApplyNum) :ApplyNum\= r35,
motion_class(ApplyNum, main),
!.
% Take from the table
121
applicable_to(MID:r35, ApplyTo) :log(event(made_motion, _, MID:r35), TU),
%See if last motion to take ApplyTo from table failed.
last_occurrence(TU, [log(resolved(_:r35, ApplyTo, failed), TL)]),
% See if any business has occurred between 1L and TU.
business_transacted(TL, TU),
!.
applicable_to(MID:r35, ApplyTo) :% See when ApplyTo was laid on table.
log(resolved(_:r28, ApplyTo, passed), TL),
log(event(made_motion, _, MID:r35), TU),
%See if any business has occurred between 1L and TU.
business_transacted(TL, TU),
!.
% Reconsider
applicable_to(MID:r36, ApplyTo) :once(not false(applicable_to(MID:r36, ApplyTo))),
!.
false( applicable_to(_:r36, _:r17)).
false( applicable_to(_:r36, _:r18)).
false( applicable_to(_:r36, _:r20)).
false( applicable_to(_:r36, _:r21q) ).
false(applicable_to(_:r36, _:r22)).
% Positive vote on Objection to Consideration of Question
false(applicable_to(_:r36, ApplyiD:r23)) :log(resolved(ApplyiD:r23, _, passed), _).
false( applicable_to(_:r36, _:r24)).
false( applicable_to(_:r36, _:r25div)).
false( applicable_to(_:r36, _:r26meth)).
false( applicable_to(_:r36, _:r26close)).
% Positive vote on Reopen Nominations
false( applicable_to(_:r36, Apply1D:r26reop)) :log(resolved(Apply1D:r26reop, _, passed), _).
false( applicable_to(_:r36, _:r27info)).
% Positive vote on Withdraw a Motion
false( applicable_to(_:r36, ApplyiD:r27cw)) :log(resolved(ApplyiD:r27c, _, passed), _).
false( applicable_to(_:r36, _:r28)).
% Previous Question after it has caused a vote to be taken.
false( applicable_to(_:r36, ApplyiD:r29)) :applies_to(ApplyiD:r29, Motion),
log(resolved(Motion,_,_),_).
false(applicable_to(MID:r36, ApplyiD:r32)) :applies_to(ApplyiD:r32, Apply2),
askable(taken_up_by_committee(Apply2)).
% Negative vote on Postpone Indefinitely.
false( applicable_to(_:r36, ApplyiD:r34)) :log(resolved(Apply1D:r34, _, failed), _).
122
false( applicable_to(_:r36, _:r35)).
false( applicable_to(_:r36, _:r3 6)).
% Positive vote on Rescind
false( applicable_to(_:r36, ApplyiD:r37)) :log(resolved(ApplyiD:r37, _,passed),_).
%Rescind
applicable_to(MID:r37, _:r2la).
applicable_to(MID:r37, ApplyTo) :motion_class(ApplyTo, main).
% *************************************************************************
% DEBATABLE
debatable(MID:r16) :forall(order(Motion, pending), Motion= MID:r16),
!.
debatable(MID:r18) :forall(order(Motion, pending), Motion= MID:r18),
!.
debatable(_:r19).
debatable(MID:r21a) :once(not false( debatable(MID:r21 a))),
!.
false(debatable(MID:r2la)) :askable(relates_to(MID:r21a, [indecorum])).
false(debatable(MID:r2la)) :askable(relates_to(MID:r21a, ['rules of speaking'])).
false(debatable(MID:r2la)) :askable(relates_to(MID:r21a, ['priority of business'])).
false(debatable(_:r2la)) :log(resolved(DiviD:r25, ApplyTo, passed), _),
order(ApplyTo, active).
false(debatable(MID:r2la)) :order(Motion, pending),
% Prevent infinite looping.
not Motion = _:r21a,
not debatable(Motion).
debatable(MID:r21q) :once(not false(debatable(MID:r21 q) )),
!.
false(debatable(MID:r21q)) :-
123
askable(relates _ to(MID:r21q, [indecorum])).
false(debatable(MID:r21q)) :askable(relates_to(MID:r21q, ['rules of speaking'])).
false(debatable(MID:r2lq)) :askable(relates_to(MID:r21q, ['priority of business'])).
false(debatable(_:r21q)) :log(resolved(DiviD:r25, ApplyTo, passed), _),
order(ApplyTo, active).
false(debatable(_:r21q)) :order(Motion, active),
% Prevent infinite looping.
not Motion = _:r21q,
not debatable(Motion).
debatable(_:r26meth).
debatable(_:r31 ).
debatable(_:r32).
debatable(MID:r33) :applies_to(MID:r33, ApplyTo),
debatable(ApplyTo),
!.
debatable(MID:r33) :askable(relates_to(MID:r33, ['filling blanks'])).
debatable(_:r34).
debatable(MID:r36) :applies_to(MID:r36, ApplyTo),
debatable(ApplyTo),
!.
debatable(Motion) :motion_class(Motion, main).
% *************************************************************************
% DECIDABLE BY CHAIR
decidable_by_chair(_:r19a).
decidable_by_chair(_:r20).
decidable_by_chair(_:r21q).
decidable_by_chair(_:r27info).
decidable_by_chair(_:r27cw) .
. decidable_by_chair(_:r27cm).
decidable_by_chair(_:r27d).
% *************************************************************************
% DOMAIN HEAD
124
domain_head( amendable(_)).
domain_head(applicable_to(_, _)).
domain_head( debatable(_)).
domain_head(debates(_,_)).
domain_head( decidable_by_chair(_)).
domain_head(dispose(_)).
domain_head(eligible_for_consideration(_,_)).
domain_head(eligible_for_consideration(_,_,_,_)).
domain_head(false(_)).
domain_head( in_order(_,_,_)).
domain_head(makes(_,_)).
domain_head( makes(_,_,_)).
domain_head( may_have_floor(_)).
domain_head(motion_class(_,_)).
domain_head(needed_to_pass(_,_)).
domain_head( obtains(_)).
domain_head(orderly_introduction(_,_)).
domain_head(putq(_)).
domain_head(resolve(_)).
domain_head(state(_)).
domain_head( vote(_)).
domain_head( vote_by_division(_)).
domain_head(yields(_)).
9b *************************************************************************
9b ELIGIBLE FOR CONSIDERATION
eligible_for_consideration(MID:r28, ApplyTo) :once(not false( eligible_for_consideration(MID:r28, ApplyTo))).
false(eligible_for_consideration(MID:r28, ApplyiD:ApplyNum)) :log(resolved(_:r28, ApplyiD:ApplyNum, failed), Tl),
log(event(made_motion, _, MID:r28), T2),
9b See if any business occurred between the time that the last
9b Lay on the Table of ApplyiD failed and MID:r28 was made.
not business_transacted(Tl, T2),
not askable(urgency(MID:r28, immediate)).
false( eligible_for__consideration(MID:r28, ApplyiD:ApplyNum)) :log(resolved(_:r35, ApplyiD:ApplyNum, passed), Tl),
log(event(made motion, , MID:r28), T2),
% See if any business occurred between ithe time that ApplyiD was taken from
9b the table and MID:r28 was made.
·
not business_transacted(Tl, T2), ,
not askable(urgency(MID:r28, immediate)).
eligible_for_consideration(MID:r36, MemiD, ApplyTo, passed):-
125
askable(voted_for(MemiD, ApplyTo)).
eligible_for_consideration(MID:r36, MemiD, ApplyTo, failed) :askable(voted_against(MemiD, ApplyTo)).
9& *************************************************************************
9& IN ORDER
9& PRIVILEGED MOTIONS
9& Fix Time to Adjourn
in_order(MID:r16, MemiD, _) :may_have_floor(MemiD),
not order(_:r16, pending),
askable(seconded(MID:r16)).
9& Adjourn
in_order(MID:rl7, MemiD, _) :may_have_floor(MemiD),
9& See if some business has occurred since Adjourn was last moved.
business_since_last_moved(MID:r17),
not order(_:r16, pending),
not order(_:r17, pending),
not assembly_state(voting),
askable(seconded(MID:r17)).
9& Recess
in_order(MID:r18, MemiD, _) :may_have_floor(MemiD),
not order(_:rl6, pending),
not order(_:rl7, pending),
not order(_:r18, pending),
askable(seconded(MID:rl8)).
9& Raise a Question of Privilege
in_order(MID:r19a, MemiD, _) :not order(_:r16, pending),
not order(_:r17, pending),
not order(_:r18, pending),
not order(_:rl9, pending),
not assembly_state(voting),
( may_have_floor(MemiD); askable(urgency(MID:r19,irnrnediate)) ).
9& Question of Privilege (as a regular motion).
in_order(MID:rl9, MemiD, _) :not order(_:r16, pending),
not order(_:r17, pending),
not order(_:rl8, pending),
not order(_:rl9, pending),
(l
126
not assembly_state( voting),
( may_have_floor(MerniD); askable(urgency(MID:rl9,irnrnediate)) ),
askable(seconded(MID:r19)).
% Call for Orders of the Day
in_order(MID:r20, _, _) :not order(_, pending),
askable(variation_from_order(MID:r20)).
in_order(MID:r20, _, _) :not class_status(privileged, pending),
askable(variation_from_order(MID:r20)),
askable(special_order_scheduled(MID:r20) ).
% INCIDENTAL MOTIONS
% Appeal
in_order(MID:r21a, _, ApplyTo) :once(not class_status(privileged,pending)),
not order(_:r21a, pending),
applicable_to(MID:r21a, ApplyTo),
askable(seconded(MID:r21a)).
% Question of Order
in_order(_:r2lq, _, _) :not class_status(privileged,pending).
% Suspension of the Rules
in_order(MID:r22, MerniD, _) :may_have_floor(MerniD),
not class_status(privileged,pending),
askable(seconded(MID:r22)).
% Objection to Consideration of a Question
in_order(MID:r23, _, ApplyTo) :once(not class_status(privileged,pending) ),
once(applicable_to(MID:r23, ApplyTo)),
order(ApplyTo, pending),
not log(event(debated, '-' ApplyTo), _),
% Check that no subsidiary motions have been stated for ApplyTo.
not ( applies_to(Motionl, ApplyTo),
motion_class(Motionl, subsidiary),
log(event(stated, Motionl), _) ).
% Division of a Question
in_order(MID:r24, MerniD, ApplyTo) :motion_class(ApplyTo, main),
order(ApplyTo, active),
•
127
orderly_introduction(MID:r24, MemiD).
in_order(MID:r24, MemiD, ApplyTo) :motion_class(ApplyTo, main),
order(PostPoneiD:r34, active),
applies_to(PostPoneiD:r34, ApplyTo ),
orderly_introduction(MID:r24, MemiD).
% Division of Assembly
in_order(MID:r25div, _, ApplyTo) :order(ApplyTo, active),
(assembly_state(put_question); assembly_state( voting)),
applicable_to(MID:r25div, Apply To).
% Motions related to Voting
in_order(MID:r25, MemiD, ApplyTo) :order(ApplyTo, active),
(assembly_state(put_question); assembly_state( voting)).
% Nominations
in_order(MID:r26meth, MemiD, _) :may_have_floor(MemiD),
not class_status(privileged,pending),
askable(seconded(MID:r26meth)).
in_order(MID:r26close, MemiD, _) :may_have_floor(MemiD),
not class_status(privileged, pending).
in_order(MID:r26reop, MemiD, _) :may_have_floor(MemiD),
not class_status(privileged,pending).
% Parliamentary Inquiry
in_order(MID:r27info, MemiD, _) :not class_status(privileged,pending),
orderly_introduction(MID:r27info, MemiD).
% Withdraw a Motion
in_order(MID:r27cw, MemiD, ApplyTo) :may_have_floor(MemiD),
once(not class_status(privileged,pending)),
order(ApplyTo, pending),
% Mover of MID is same as mover of ApplyTo
log(event(made_motion, MemiD, ApplyTo), _),
not (order(ApplyTo, active), assembly_state(voting)).
% Modify a motion
in_order(MID:r27cm, MemiD, ApplyTo) :in_order(MID:r27cw, MemiD, ApplyTo ).
128
% Reading Papers
in_order(MID:r27d, MemiD, _) :may_have_floor(MemiD),
not class_status(privileged, pending),
askable(seconded(MID:r27d) ).
% SUBSIDIARY MOTIONS
% Lay on the Table
in_order(MID:r28, MemiD, ApplyTo) :may_have_floor(MemiD),
( motion_class(ApplyTo, privileged);
not class_status(privileged,pending) ),
order(ApplyTo, pending),
once(eligible_for_consideration(MID:r28, ApplyTo) ),
once(applicable_to(MID:r28, ApplyTo) ),
askable(seconded(MID:r28)).
% Previous Question
%
applied to any debatable or amendable motion
in_order(MID:r29, MemiD, ApplyTo) :may_have_floor(MemiD),
order(ApplyTo, pending),
once(applicable_to(MID:r29, ApplyTo) ),
% Make sure no other privileged or incidental motions
% other than ApplyTo are pending.
forall(( order(Motion, pending),
motion_class(Motion, Class),
member(Class, [privileged, incidental])),
Motion= ApplyTo),
not order(_:r28, pending),
askable(seconded(MID:r29) ).
% Limit or Extend Limits of Debate
% applied to any debatable motion
in_order(MID:r30, MemiD, ApplyTo) :may_have_floor(MemiD),
order{ApplyTo, active),
once(debatable(ApplyTo)),
% Make sure no privileged or incidental motions other than
% ApplyTo are pending.
129
forall( (order(Motion, pending),
motion_class(Motion, Class),
member(Class, [privileged, incidental])),
Motion= ApplyTo),
not order(_:r28, pending),
not order(_:r29, pending),
askable(seconded(MID:r30) ).
% Postpone Definitely
in_order(MID:r31, MerniD, ApplyTo) :may_have_floor(MerniD),
order(ApplyTo, pending),
once(not class_status(privileged,pending)),
once(not class_status(incidental, pending)),
not order(_:r28, pending),
not order(_:r29, pending),
not order(_:r30, pending),
askable(seconded(MID:r31 )).
% Commit or Refer
in_order(MID:r32, MerniD, ApplyTo) :may_have_floor(MerniD),
once(not class_status(privileged,pending)),
once(not class_status(incidental,pending)),
not order(_:r28, pending),
not order(_:r29, pending),
not order(_:r30, pending),
not order(_:r31, pending),
once(applicable_to(MID:r32, ApplyTo) ),
askable(seconded(MID:r32) ).
% Amend
% applied to any amendable motion
in_order(MID:r33, MerniD, ApplyTo) :may_have_floor(MerniD),
arnendable(ApplyTo),
order(ApplyTo, pending),
% Make sure no privileged, incidental or subsidiary motions
% other than ApplyTo, r24, or r34 are pending.
forall( (order(Motion,pending),
motion_class(Motion,Class ),
member(Class,[privileged, incidental, subsidiary])),
member(Motion, [ApplyTo, _:r24, _:r34])),
askable(seconded(MID:r33) ).
130
% Postpone Indefinitely
% applied to a main motion
in_order(MID:r34, MemiD, ApplyTo) :may_have_fioor(MemiD),
order(ApplyTo, pending),
motion_class(ApplyTo, main),
once(not class_status(privileged,pending) ),
once(not class_status(incidental, pending)),
not class_status(subsidiary,pending),
askable(seconded(MID:r34)).
% OTHER MOTIONS
% Take From Table
in_order(MID:r35, MemiD, ApplyTo) :may_have_fioor(MemiD),
not order(_, pending},
once(applicable_to(MID:r35, ApplyTo}},
askable(seconded(MID:r35) ).
% Reconsider
in_order(MID:r36, MemiD, ApplyTo) :may_have_fioor(MemiD},
log(resolved(ApplyTo, _,Outcome},_},
once(eligible_for_consideration(MID:r36, MemiD, ApplyTo, Outcome)),
once(applicable_to(MID:r36, ApplyTo}),.
askable(seconded(MID:r36)).
% Rescind, Repeal, or Annul
in_order(MID:r37, MemiD, ApplyTo) :may_have_fioor(MemiD),
not order(_, pending},
% Make sure ApplyTo has already been voted on.
once((log(resolved(ApplyTo, _, _}, _); tentative_result(ApplyTo,_,_})},
not askable(irreversible(ApplyTo)},
applicable_to(MID:r37, ApplyTo},
askable(seconded(MID:r37)).
% Main Motion
in_order(MID:main, MemiD, _) :%No other motion is pending.
not order(_, pending),
may_have_fioor(MemiD),
askable(seconded(MID:main) ).
131
% *************************************************************************
% MAY_HAVE_FLOOR
% MemiD already has the floor.
may_have_floor(MemiD) :has_floor(MemiD).
% Any member may have floor if no one else does.
may_have_floor(_) :not has_floor(_).
% *************************************************************************
% MOTION CLASS
motion_class(ID:RNUM, Type):motion_class(RNUM, Type),
!.
motion_class(rl6, privileged).
motion_class(r17, privileged).
motion_class(rl8, privileged).
motion_class(rl9a, privileged).
motion_class(r19, privileged).
motion_class(r20, privileged).
motion_class(r2la, incidental).
motion_class(r21q, incidental).
motion_class(r22. incidental).
motion_class(r23, incidental).
motion_class(r24, incidental).
motion_class(r25, incidental).
motion_class(r25div, incidental).
motion_class(r26meth, incidental).
motion_class(r26close, incidental).
motion_class(r26reop, incidental).
motion_class(r27info, incidental).
motion_class(r27cw, incidental).
motion_class(r27cm, incidental).
motion_class(r27d, incidental).
motion_class(r28, subsidiary).
motion_class(r29, subsidiary).
motion_class(r30, subsidiary).
motion_class(r31, subsidiary).
motion_class(r32, subsidiary).
motion_class(r33, subsidiary).
motion_class(r34, subsidiary).
motion_class(r35, main).
motion_class(r36, special).
132
motion_class(r37, main).
motion_class(main, main).
~
~
*************************************************************************
NEEDED_TO_PASS
needed_to_pass(_:r22, two_thirds).
needed_to_pass(_:r23, two_thirds).
needed_to_pass(_:r26c, two_thirds).
needed_to_pass(_:r29, two_thirds).
needed_to_pass(_:r30, two_thirds).
needed_to_pass(MID:r37, two_thirds) :not askable(notice_given(MID:r37)).
~ Default for all other motions.
needed_to_pass(_, majority).
~
~
*************************************************************************
ORDERLY INTRODUCTION
orderly_introduction(MID:r24, _) :askable(subject(MID:r24, multiple)).
orderly_introduction(MID:r24, MemiD) :has_floor(MemiD),
askable(seconded(MID:r24) ).
orderly_introduction(_:r27info, MemiD) :has_floor(MemiD).
orderly_introduction(MID:r27info, _) :askable(urgency(MID:r27info, immediate)).
9&
~
*************************************************************************
PRECEDENCES
precedences([r16,rl7,rl8,rl9a,rl9,r20,r21a,r21q,r22,r23,r24,r25div,r25,r26meth,
r26close,r26reop,r27info,r27cw,r27cm,r27 d,r28,r29,r30,r31,
r32,r33,r34,r35,r36,main,r37]).
~
*************************************************************************
9& RULE NUMBER
rule_number('Fix Time to Adjourn', r16).
rule_number(' Adjourn', r17).
133
rule_number('Recess', r18).
rule_number(' Question of Privilege', r19).
rule_number(' Call for Orders of the Day', r20).
rule_number(' Appeal', r21a).
rule_number('Question of Order', r2lq).
rule_number('Suspension of the Rules', r22).
rule_number(' Objection to Consideration of a Question', r23).
rule_number('Division of a Question', r24).
rule_number(' Division of Assembly', r25div).
rule_number('Motions Relating to Voting', r25).
rule_number('Method of Nomination', r26meth).
rule_number(' Close Nominations', r26close).
rule_number(' Reopen Nominations', r26reop).
rule_number('Parliamentary Inquiry', r27info).
rule_number('Withdraw a Motion', r27cw).
rule_number('Modify a Motion', r27cm).
rule_number('Reading Papers', r27d).
rule_number('Lay on the Table', r28).
rule_number(' Previous Question', r29).
rule_number('Limit or Extend Debate', r30).
rule_number(' Postpone Definitely', r31 ).
rule_number(' Commit or Refer', r32).
rule_number(' Amend', r33).
rule_number('Postpone Indefinitely', r34).
rule_number(' Take from Table', r35).
rule_number('Reconsider', r36).
rule_number(' Rescind, Repeal, or Annul', r37).
rule_number('Main Motion', main).
134
%file name:
%purpose:
%modules:
interp.pl
Rule interpreters
CMI andERI
% *************************************************************************
% ASKABLE
% The Consultation Mode Interpreter
% If Pred is already provable then succeed.
askable(Pred) :call(Pred), !.
askable(Pred) :% See if the negation of Pred is provable. If so then fail.
negate(Pred, NegPred),
not NegPred,
prolog_to_english(Pred, Trans),
% Ask user whether Pred is true.
prompt_cycle((nl,nl,
write('ls it true that'), nl,
write_list(Trans, write(' ')), write('?'), nl,
write('[yes. I no.] > ')),
yes_or_no(_, Resp)),
(Resp = yes ->
assert(Pred)
I
% If user says Pred is false then fail.
assert(NegPred), !, fail),
!.
% *************************************************************************
%COPY TERM
% Make a copy of a term with different variables
copy terni(Term, Copy) ::findall(X, X=Term, [Copy]),
!.
% *************************************************************************
% EXPROVE
% The Explanation Rule Interpreter.
135
% Produces a trace of the proof as a side effect.
exprove(Goal) :exprove(O, Goal), !.
% exprove(Indent, Goal) -- Indent is the number of spaces to indent the
% explanation and Goal is the goal to be explained.
% Conjunction
exprove(L, (A, B)) :-
'.,
exprove(L, A),
exprove(L, B).
% Disjunction
exprove(L, (A; B)) :-
.,
'
(exprove(L, A); exprove(L, B)).
% Explain the Goal inside once/ 1. Execute Goal
% once only· (no backtracking).
exprove(L, once(Goal)) :-
.,'
exprove(L, Goal),
!.
exprove(L, not Goal) :(not exprove(L, Goal) ->
storenode(pt(L, (not Goal :- true)))
I
storenode(pt(L, failed(not Goal))), !, fail).
% If Goal is a "procedure" then store a node for it but don't explain
% it any further. Goal is called directly.
exprove(L, Goal) :procedure(Goal),
.,
'
(Goal->
storenode(pt(L, (Goal :- true)))
I
storenode(pt(L, failed(Goal))), !, fail).
% If Goal is a "knap_predicate" then don't explain it at all, just see
%if it is provable. knap_predicate's are hidden from the user.
exprove(_, Goal) :knap_predicate(Goal),
.,'
Goal.
% Goal is a regular goal. See if there is a clause with Goal as head.
136
% If so try to prove the body.
exprove(L, Goal) :clause(Goal, Body),
% Store a node that shows the full rule with variables instantiated to
% unique id's.
storenode(pt(L, (Goal :-Body))),
(Body = true ->
% Succeed if Goal is a fact.
true
I
% Otherwise prove Body.
assert(pt(_, line_feed)),
% Add 4 to the number of spaces to indent so that explanation
% of rule will be indented under display of rule.
plus(L, 4, Ll),
exprove(Ll, Body),
% If Body succeeds then store a node to that effect.
storenode(pt(L, (Goal :- true)))).
% If there is no clause for Goal and the above clauses failed then
% assert a failure node and fail.
exprove(L, Goal) :not pt(_, (Goal :- true)),
storenode(pt(L, failed(Goal))),
!, fail.
% *************************************************************************
% STORENODE
storenode(X) :% Make a copy of X with different variables.
copy_term(X, XCopy),
% Assign unique constants to the variables in the copy.
numbervars(XCopy, 0, _),
%Store the copy in memory.
assert(XCopy),
!.
137
%file name:
%purpose:
%module:
top.pl
The KNAP User Intetface.
UI
% *************************************************************************
% EXIT_MESSAGE
exit_message :output((nl, write('
KNAP Session Completed'))).
% *************************************************************************
% KNAP
% The top level call to KNAP.
knap :% Clear the screen.
put(26),
% Give KNAP header.
startup_message,
% Start repeat-fail loop.
repeat,
read_input(lnput),
% Process input and fail back to repeat if not "halt".
process_input(Input),
exit_message.
% *************************************************************************
% PROCESS INPUT
% If command is "halt" then output minutes and exit.
process_input(halt) :- minutes.
% Otherwise process the input and fail back to beginning of repeat loop.
process_input(lnput) :process_inputl (Input),
% Fail back to repeat after processing input.
!, fail.
% *************************************************************************
% PROCESS INPUTl
% yes/no question.
138
process_inputl(q(Query)) :(Query->
output((nl,nl, write('Yes')))
I
output((nl,nl, write('No')))),
!.
% WH question.
process_inputl(q(Vars, Query)) :findall(V ars, Query, Answers 1),
sort(Answersl, Answers),
(Answers = 0 ->
output((nl,nl, write('No answers found')))
I
output((nl,nl, write(' Answers:'),
forall(member(E, Answers),
(nl,tab(8), write_Iist(E, write(', ')))) ))),
!.
% State update for Put Question.
process_inputl(put(M)) :-
.,
'
% Delete all previous proof-tree nodes.
retractall(pt(_,_) ),
% Must call putq/1 instead of put/1 because put/1
% is a predefined Prolog predicate.
process_update(putq(M)).
% State update
process_inputl(Action) :valid_action( Action),
% Delete all previous proof-tree nodes.
retractall(pt(_,_) ),
process_update( Action),
!.
%Top level command
process_inputl(Command) :valid_command(Command),
Command,
!.
% Input is not recognized.
process_inputl(Term) :output((nl, nl, write_mess(['Sorry I don"t understand',Term]))).
% *************************************************************************
% PROCESS UPDATE
% Process a state update.
process_update(Action) :-
139
exprove(Action),
.,'
output((nl, nl, write(' Action accepted'))).
% If exprove(Action) fails then Action is illegal.
process_update(Action) :output((nl,nl, write('ILLEGAL ACTION'))),
% Output the English translation of all failed nodes in the proof.
findall(NegR,
(pt(_,failed(R)), translate_and_negate{R, NegR)),
Reasons),
output((nl,nl, forall(member(Reason,Reasons),(write_ mess(Reason),nl))) ),
!.
% *************************************************************************
% READ INPUT
% Prompt for input and read input
read_input(IN) :output((nl, nl, write('READY> '))),
read_and_echo(IN),
!.
% *************************************************************************
% STARTUP MESSAGE
startup_message :output((nl, write('
KNAP
THE KNOWLEDGE BASED AUTOMATED PARLIAMENTARIAN'), nl, nl)).
% *************************************************************************
% VALID ACTION
valid_action(obtains(_)).
valid_action(yields(_) ).
valid_action(mak:es(_,_)).
valid_action(state(_)).
valid_action( debates(_,_)).
valid_action(resolve(_)).
valid_action( vote(_)).
valid_ action( vote_by_division(_)).
valid_action( dispose(_)).
140
9.0 ****************~********************************************************
9.0 VALID_COMMAND
valid_command(explain).
valid_command(initialize).
valid_command( minutes).
valid_command(pending).
valid_command(script _).
valid_command(show).
valid_command(what_now).
valid_command( why).
9.0 Trap numbers so that system_predicate(Num) is not called.
valid_command(Num) :- number(Num), !, fail.
valid_command(Command) :- system_predicate( Command).
141
% file name:
% purpose:
% module:
code
Miscellaneous System Procedures for KNAP
SP
% These are the Top level predicates.
% Top level predicates are either called by predicates defined in some
% other KN AP file, or are called by more than one predicate defined
% in this file.
% They are listed alphabetically by predicate name.
% Lower level predicates called by a top level predicate are defined
% immediately below the top level predicate in top-down order.
% *************************************************************************
% ADD PENDING MOTION
% Add a motion to the pending stack.
% Motion to Reconsider must be inserted into pending stack at place
% where ApplyTo would normally be in order.
add_pending_motion(Member, MID:r36) :-
.,
'
applies_to(MID:r36, ApplyTo),
insert_reconsider(MID:r36, ApplyTo),
!.
% Catch-all for all other motions.
add_pending_motion(Member, Motion) :update_pending(Member, Motion).
% Insert a motion to Reconsider at the point in the pending stack where
% The motion to be reconsidered would be in order
insert_reconsider(Reconsider, ApplyiD:ApplyNum) :retract(stack(pending, Stack)),
outranked_by(ApplyNum, Higher),
insert_reconsider(Reconsider, ApplyNum, Higher, Stack, OutStack),
assert(stack(pending, OutStack)),
!.
insert_reconsider(Reconsider, _, _, [],
[context(considering_motion,Reconsider,#)]) :!.
insert_reconsider(Reconsider, RNum, Higher, [context(St,MID:RNum2,Mem) I Stack],
[context(St,MID:RNum2,Mem) 1 OutStack]) :% If the top motion is of higher precedence than the motion to be
% reconsidered, go to the next motion in the stack.
member(RNum2, Higher),
I.,
{\
142
insert_reconsider(Reconsider, RNum, Higher, Stack, OutStack).
% If the top motion is not of higher precedence than the motion to be
% reconsidered then insert the Motion to Reconsider before the top motion.
insert_reconsider(Reconsider, RNum, _, Stack,
[context(considering_motion,Reconsider,#) 1 Stack]).
% Find rule numbers of motions of higher precedence than RN urn.
outranked_by(RNum, List) :% Get the Stack of rule numbers in order of precedence.
precedences(Motions),
.
% Get the sub-stack of higher precedence rule numbers.
extract_higher_stack(Motions, RNum, List).
%Find all elements in a stack on top of element Item.
% If Item is found then sub-stack is complete.
extract_higher_stack([Item!Stack], Item, []) :- !.
% If Item has not yet been found then put top element into output list.
extract_higher_stack([El!E2], Item, [El!OutStack]) :% Continue searching for Item and extracting higher elements.
extract_higher_stack(E2, Item, OutS tack).
% If Item is not found then return empty list
extract_higher_stack(O, _, []).
~
**************************************************************************
% ADHERES TO
% Any motion adheres to itself
adheres_to(Motion, Motion) :- !.
% X adheres to Y if X applies to Y.
adheres_to(Motionl, Motion2) :applies_to(Motionl, Motion2),
!.
%Transitivity ofadheres_to
adheres_to(Motionl, Motion2) :applies_to(Motionl, Motion3 ),
adheres_to(Motion3, Motion2),
!.
~
**************************************************************************
~
ASK_ABOUT_MOTION
~
Ask the user which motion a new motion applies to, if any.
.
143
ask_about_motion(RNum, MID:RNum, ApplyTo) :gen_motion_id(MID),
output((nl,nl, write('The ID for this new motion is '), write(MID))),
% Should have special routine for next input that knows when
% an ApplyTo motion is needed and when not.
prompt_cycle(
(nl, nl,
write('To which motion will this new motion apply?'),
nl, write('Enter the motion ID (if none enter "n.") > ')),
valid_applied_to(_, ApplyTo )),
!.
%Generate a unique motion ID.
gen_motion_id(ID) :retract(next_motion_id(ID)),
succ(ID, IDI),
assert(next_motion_id(ID 1)),
!.
% Generate a motion ID for the first time in a session.
gen_motion_id(l) :assert(next_motion_id(2)).
valid_applied_to(none, none) :- !.
valid_applied_to(n, none) :- !.
valid_applied_to(MID:RNum, MID:RNum) :number(MID),
atomic(RNum),
!.
% Find the rule number for motion number ID that is pending.
valid_applied_to(MID, MID:RNum) :number(MID),
order(MID:RNum, pending),
!.
% Find the rule number for motion number ID that has been resolved.
valid_applied_to(MID, MID:RNum) :number(MID),
log(resolved(MID:RNum,_,_),_),
!.
valid_ applied_to(Motion, _) :invalid_input(Motion, 'motion identifier').
% **************************************************************************
% ASK_ABOUT_QOP
144
% Ask the user if s/he is making a formal motion for
% Question of Privilege. Succeed if the answer is no.
ask_about_qop(~ember)
:prompt_cycle(
(nl, nl, write_mess(['Is' ,Member,'making a formal motion of this',
'question of privilege?']), nl,
write('[yes. I no.] > ')),
yes_or_no(_, Answer)),
Answer= no,
!.
% **************************************************************************
- ~OVED
% BUSINESS SINCE LAST
-
-
% See if any substantive business has occurred since a motion type was
% last moved.
%A motion of type RNum was not previously made.
business_since_last_moved(~ID:RNum) :forall(log(event(made_motion, _, ~ID2:RNum),_), ~ID = ~ID2),
!.
%A motion of type RNum was previously made.
business_since_last_moved(~ID:RNum) :log(event(made_motion, _, ~ID:RNum), TU),
%Find the time tag of the making of motion RNum or the failure of
% motion RN urn, whichever came last.
last_occurrence(TU, [log(resolved~ID2:RNum, _,failed), TL),
log(event(made_motion, _, ~ID2:RNum), TL)]),
% See if any business occurred between time TL and the time that
% ~ID:RNum was made.
business_transacted(TL, TU),
!.
%
%
%
%
%
For a list of log entries List find the time tag of the event in List
that occurred last.
last_occurrence(Start, List) -- Start is the time at which the search
begins. It is decremented until one of the log entries in List is found,
or until Start becomes zero.
% If the counter gets to zero then none of the events in List ever occurred.
last_occurrence(O, _) :- !, fail.
last_occurrence(T, List) :%Decrement T.
succ(Tl, T},
% If there is a log entry with time T1 then succeed.
145
( log(Event, Tl), member(log(Event, Tl), List);
% Otherwise continue the search by decrementing Tl.
last_occurrence(Tl, List) ),
!.
% See if any substantive business occurred between time Lower and time
%Upper.
business_transacted(Lower, Upper) :succ(Lower, Beginning),
business_transacted I (Beginning, Upper).
% If the new lower and upper bounds are equal then fail because no business
% has taken place since the original lower bound time.
business_transactedl(E, E) :- !, fail.
% Succeed if event at time B was anything other than obtaining floor.
business_transactedl(B, E):log(Event, B),
not Event= event(obtained_floor,_),
!.
% If no business occurred at time B then increment B and see if anything
% happened at that time.
business_transactedl(B, E) :business_transacted(B, E).
% **************************************************************************
% CLASS STATUS
% A class of motion is pending (active) if any motion of that class is
%pending (active).
class_status(Class, Status) :order(_:RNum, Status),
motion_class(RNum, Class).
% *************************************************************************
%CARRY OUT
% Carry out a motion if it passed.
%Do nothing for failed motions except pop the motion's context tuple
% off the pending stack.
carry_out(_, _,failed) :pop(pending, _).
% If there are not enough votes for a quorum then simply pop the motion
% off the pending stack.
146
carry_out(Motion, _, insufficient_votes) :output((nl, nl,
write('The total number of votes does not satisfy a quorum.'),
nl, write_mess([motion,Motion,'is being disposed of without',
'resolution.']), nl)),
pop(pending, _).
%ADJOURN
% ------carry_out(MID:r17, _,passed) :pop(pending, _),
prompt_cycle((nl, nl,
write('Do you want to save the current state of this session?'),
nl, write('Enter yes or no> ')),
yes_or_no(_, Resp) ),
(Resp = yes ->
prompt_cycle((nl, nl,
write('Under what file name?'),
nl, write(' > ')),
atomic(File)),
output((nl, nl, write('Saving current state .. .'))),
save(File),
output((nl, nl, write('Current state saved.')))
I
true),
!.
% CALL FOR ORDERS OF THE DAY
% --------------------------
% If there are no orders of the day then do nothing.
carry_out(MID:r20, _, passed) :not order_of_the_day(_,_),
output((nl, write('There are no orders of the day'))),
!.
% Find out which order of the day is being called for.
carry_out(MID:r20, _, passed) :prompt_cycle((nl, nl,
write('Enter the time identifier of the order of the day'),
write(' that has been called for'), nl,
write(' enter 24-hour time > ')),
valid_time(Time)),
order_of_the_day(OrdStack, Time),
% _ OrderiD is the context for motion MID:r20. It is not needed anymore.
retract(stack(pending, [_OrderiD I Stack])),
% Push the stack of orders of the day on top of the pending stack.
append(OrdStack, Stack, NewStack),
147
assert(stack(pending, NewStack)),
!.
% OBJECTION TO CONSIDERATION OF A QUESTION
% --------------------------------------carry_out(MID:r23, ApplyTo, passed) :pop(pending, _),
output((nl, nl,
write_mess(['Motion' ,ApplyTo, 'has been removed',
'from consideration.']))),
!.
% DIVISION OF A QUESTION
% ---------------------
% Divide a motion into two or more motions and push them onto
% the pending stack.
carry_out(MID:r24, ApplyTo, passed) :. output((nl,nl, write_mess(['Motion' ,ApplyTo, 'will now be divided into',
'multiple motions.']))),
prompt_cycle((nl, nl,
write('How many motions will there be?'), nl,
write(' > ')),
number(N)),
% Get rid of contexts for MID:r24 (_DivCxt) and ApplyTo (ApplyCxt).
retract(stack(pending, [_DivCxt, ApplyCxt I Stack])),
add_n_pending_motions(ApplyCxt, N, Stack),
!.
%Generate N unique motion ill's and add a context tuple for each ID
% to the pending stack.
add_n_pending_motions(context(State,MID:RNum,Member), N, Stack) :gen_n_motion_ids(N, IDs, RNum),
inform(new_ids, IDs),
findall(context(considering_motion,ID,#), member(ID, IDs), Contexts),
append(Contexts, Stack, NewStack),
assert(stack(pending, NewStack)),
!.
% Generate a list of N unique ill's.
gen_ n_ motion_ids(O, [], _) :- !.
gen-n-motion- ids(N, [ID:RNum I IDs], RNum) :gen_motion_id(ID),
succ(Nl, N),
148
gen_n_motion_ids(Nl, IDs, RNum),
!.
%Tell the user the new motion ID's.
inform(new_ids, IDs) :output((nl, nl,
write('The new motion ID"s are· (in order of consideration):'),
nl, tab(8),
write;_list(IDs, (nl, tab(8))))),
!.
% WITHDRAW A MOTION.
% ---------------carry_out(MID:r27cw, ApplyTo, passed) :% WDCxt is the context for motion MID:r27cw. It is not needed anymore.
retract(stack(pending,[_WDCxt I Stack])),
extract_adhering_motions(Stack, ApplyTo, Set),
output((nl, nl,
write_mess(['Motion',ApplyTo,'and all motions that adhere',
'to it have been withdrawn.']))),
!.
% LAY ON 1HE TABLE.
% ---------------carry_out(MID:r28, ApplyTo, passed) :% _LayCxt is the context for motion MID:r28. It isn't needed anymore.
retract(stack(pending,[ LayCxt I Stack])),
extract_adhering_motions(Stack, ApplyTo, Set),
% Record that fact that the extracted motions were laid on the table.
assert(laid_on_table(ApplyTo, Set)),
output((nl, nl,
write_mess(['Motion' ,ApplyTo,' and all motions that adhere',
'to it have been laid on the table.']))),
!.
% PREVIOUS QUESTION
% ----------------carry_out(MID:r29, ApplyTo, passed):%Get rid of motion MID:r29.
pop(pending, _),
update_state(debate),
update_fioor(#),
149
% Put motion ApplyTo to the assembly for vote.
putq(ApplyTo),
!.
% POSTPONE DEFINITELY
% ------------------
carry_out(MID:r31, ApplyTo, passed) :% _PostponeCxt is the context for motion MID:r31. It isn't needed anymore.
retract(stack(pending, [_PostponeCxt I Stack])),
extract_adhering_motions(Stack, ApplyTo, Set),
% Find out the time to which ApplyTo and its adhering motions will be
% postponed.
prompt_cycle((nl, nl,
write_mess(['To what time will' ,ApplyTo,'be postponed?']), nl,
write('enter 24-hour time> ')),
valid_time(Time) ),
% Change all has_floor arguments to '#' in Set context tuples.
findall( context(State,Motion,#),
member(context(State,Motion,_), Set),
Set2),
%Record ApplyTo and its adhering motions as orders of the day.
assert( order_of_the_day(Set2, Time)),
output((nl, nl,
write_mess(['Motion' ,ApplyTo,' and all motions that adhere to it',
'are postponed until' ,Time]))),
!.
% COMMIT
% ------
carry_out(MID:r32, ApplyTo, passed) :% _CommitCxt is the context for motion MID:r32. Not needed anymore.
retract(stack(pending,[_CommitCxt I Stack])),
extract_adhering_motions(Stack, ApplyTo, Set),
%Find out the name of the committee and record it in the KB.
prompt_cycle( (nl, nl,
write('To what committee will the motion be referred?'),
nl, write('enter a unique ID > ')),
atomic(Comm)),
assert(referred_to(Set, Comm)),
!.
% POSTPONE INDEFINITELY
% --------------------carry_out(MID:r34, ApplyTo, passed) :-
150
retract(stack(pending,Stack) ),
extract_adhering_motions(Stack, ApplyTo, _),
!.
% TAKE FROM TABLE
% ---------------
carry_out(MID:r35, ApplyTo, passed) :pop(pending, _),
% Get ApplyTo and all its adhering motions.
retract(laid_on_table(ApplyTo, Set)),
% _ TakeCxt is the context for MID:r35. Not needed anymore.
retract(stack(pending,(_TakeCxt I Stack])),
% Push Set onto the pending stack.
append(Set, Stack, NewStack),
assert( stack(pending,NewStack)),
!.
% DEFAULT for all other motions
% ------carry_out(Motion, ApplyTo, passed):pop{pending, _),
!.
% **************************************************************************
% CONDITIONAL
% Call the built-in Prolog predicate ->/2.
conditional{A,B,C) :{A-> B;C),
!.
% **************************************************************************
% EXTRACT ADHERING MOTIONS
% Find and extract all motions adhering to ApplyTo in Stack.
extract_adhering_motions(Stack, ApplyTo, Set) :% Find all motions that adhere to ApplyTo.
findall( context( State,Motion,Member),
(member(context(State,Motion,Member), Stack),
adheres_to(Motion, ApplyTo )),
Set),
151
% Subtract them from the pending stack and assert the difference as the
% new pending stack.
set_difference(Stack, Set, N ewStack),
assert(stack(pending,NewStack)),
!.
~
**************************************************************************
~EVEN
~See if Num is an even integer.
even(Num) :0 is Num mod 2.
% **************************************************************************
% INPUT DECISION
% Ask for the Chair's decision on a motion.
input_decision(Motion, Result) :prompt_cycle((nl, nl,
write('What is the Chair"s decision on motion '),
write(Motion), write('?'), nl, write('[pass. I fail.] > ')),
valid_decision(_, Result)),
!.
valid_decision(pass, passed) :- !.
valid_decision( fail, failed) :- !.
valid_decision(D, _) :invalid_input(D, decision).
~
**************************************************************************
% INVALID INPUT
~
Output an error message and fail.
invalid_input(Input, Type) :output((nl, nl, write_mess([Input,'is not a valid' ,Type]))),
!, fail.
% **************************************************************************
152
% MAKING MOTION
% Find out if the user is making a motion.
making_motion(MemiD, RNum) :prompt_cycle(
(nl,nl,
write('Is member '), write(MemiD), write(' making a motion?'),
nl, write(' [yes or no] > ') ),
yes_or_no(_, Resp)),
Resp =yes,
%If user is making a motion find out what rule number.
prompt_cycle(
(nl, nl, write('Which motion is being made?'),
nl, write('Enter the motion rule number> ')),
valid_rule_num(RN urn)),
!.
valid_rule_num(RNum) :rule_number(_, RNum),
!.
valid_rule_num(RNum) :invalid_input(RNum, 'rule number').
% **************************************************************************
%NEGATE
% Negate a PKRL term.
negate(askable(X), Neg) :- negate(X, Neg), !.
negate(false(X), X) :- !.
negate(not(X), X):- !.
negate(once(X), Neg) :- negate(X, Neg), !.
negate((A, B), (not(A); not(B))) :- !.
negate((A; B), (not(A), not(B))) :- !.
negate(X, false(X)).
% **************************************************************************
% PADDING NEEDED
% Find the number of spaces needed to pad output to the next word.
% Padding is (length of Word- input Length).
padding_needed(Length, Word, Padding) :-
153
name(Word, String),
length(String, StrLen),
plus(Padding, StrLen, Length),
!.
% **************************************************************************
% SET DIFFERENCE
% S 1 and S2 are sets, Diff is S l'\.S2.
set_difference(O, _, 0).
set_difference([Elemen~Residue],
Set, Difference) :identical_member(Element, Set),
.,I
set_difference(Residue, Set, Difference).
Set, [ElementiDifference]) :set_difference(Residue, Set, Difference).
set_difference([Elemen~Residue],
% identical_member(Term, List) -% Find the term Elmt in List such that Term == Elmt.
identical_member(X, [El I E2]) :X== El.
identical_member(X, [_ I E2]) :identical_member(X, E2).
% **************************************************************************
% TIME_SEQUENCE
%generate the next number in the time sequence.
time_sequence(Tag) :retract(current_tag(Tag)),
succ(Tag, NewTag),
assert(current_tag(NewTag)),
!.
% Generate the first time tag for a session.
time_sequence(l) :assert(current_tag(2)).
% *********************************~****************************************
% VALID TIME
% Make sure input is a valid 24-hour tirpe.
154
valid_time(2400) :- !.
valid_time(Time) :H is Time//100,
M is Time mod 100,
1 =<H,
H =< 23,
0 =<M,
M =<59,
!.
valid_time(Time) :invalid_input(Time, time).
9& **************************************************************************
9& VOTE ON
9& Take a vote on a motion.
vote_on(Motion) :applies_to(Motion, ApplyTo ),
retractall(tentative_result(Motion, ApplyTo, _)),
take_vote(Motion, Result),
assert(tentative_result(Motion, ApplyTo, Result)),
inform(vote_result, Motion, ApplyTo, Result),
!.
take_vote(Motion, Result) :prompt_cycle((nl, nl,
write('Enter the number of votes in favor of motion '),
write(Motion), nl, write(' > ')),
number(For)),
prompt_cycle((nl, nl,
write('Enter the number of votes against motion '),
write(Motion), nl, write(' > ')),
number(Against)),
prompt_cycle((nl, nl,
write('Enter the number of abstentions '),
nl, write(' > ')),
number(Abstain)),
once(needed_to_pass (Motion, Size)),
quorum size(Quorum),
calculate_vote_result(Size, Quorum, For, Against, Abstain, Result),
!.
' .
155
% Check to see if total votes is less than a quorum.
calculate_vote_result(_, Quorum, For, Against, Abstain, insufficient_votes) :Sum is For + Against + Abstain,
Sum < Quorum,
!.
% Calculate result for a majority-to-pass.
calculate_vote_result(majority, _,For, Against, Abstain, passed) :Sum is For + Against + Abstain,
(even(Sum) ->
Needed is (Sum I 2) + 1;
%Needed should be Sum/2 if 112 rounded up.
Needed is Sum I 2),
For >= Needed,
!.
% Calculate result for two-thirds-to-pass.
calculate_vote_result( two_thirds, _, For, Against, Abstain, passed) :Sum is For + Against + Abstain,
Needed is (2 * Sum) I 3,
For >= Needed,
!.
% If none of the above succeed then the motion failed.
calculate_vote_result(_, _, _, _, _, failed).
inform(vote_result, Motion, ApplyTo, Result) :output((nl,nl, write('The result of the vote on motion '),
write(Motion ),
(ApplyTo = none ->
true
I
write(' applied to motion '), write(ApplyTo)),
write(' : '), write(Result))).
9& **************************************************************************
9& YES OR NO
9& Test if input is one of {yes,y,no,n}.
yes_or_no(yes, yes).
yes_or_no(y, yes).
yes_or_no(no, no).
yes_or_no(n, no).
156
%file name:
%purpose:
%module:
com.pi
KNAP command execution.
SP
% explain/0 is defined in explain.pl
% **************************************************************************
% INITIALIZE
% Initialize KNAP State Model.
initialize :% Tum off Prolog system flag unknown/2 so that
% undefined predicates are not reported to user.
unknown(_, off),
retractall(log(__,_) ),
retractall(current_tag(_)),
retractall(next_motion_id(__)),
retractall(stack(pending,_) ),
% Initialize an empty pending stack.
assert(stack(pending, 0)),
retractall(quorum_size(__)),
assert(quorum_size( 10)).
% **************************************************************************
% MINUTES
% Output the English translation of the log entries of a session.
minutes:output((write('
Minutes of Session'), nl)),
forall( (log(E, T), translog(E, T,English) ),
output((nl, write_mess(English)))),
!.
% translog/3 is defined in translate.pl
% **************************************************************************
% PENDING
% Show the user the pending stack.
pending :stack(pending, Stack),
157
(Stack= 0 ->
output( write('
No motions currently pending'))
I
output(( write('
Motions currently pending'), nl,nl,
tab(8), write('State'), tab(20), write('Motion'),
tab(20), write('Has Floor'), nl,
tab(8), write('-----'), tab(20), write('------'),
tab(20), write('--------'))),
forall(member(Context, Stack), display_context(Context))),
!.
display_context(context(State,Motion,Member)) :(State = # -> PState = none; PState = State),
(Motion = # -> PMotion = none; PMotion = Motion),
(Member=#-> PMember =none; PMember =Member),
padding_needed(25, PState, Pad),
output((nl, tab(8), write(PState), tab(Pad), write(PMotion),
tab(21), write(PMember))),
!.
% *************************************************************************
%SHOW
% Show the user the domain model.
% Print a menu.
show:prompt_cycle((nl, nl,
write('What would you like to see?'), nl,
forall(member(Num-Item,
[1-'Domain Facts',
2-'Domain Rules',
3-'Domain Predicate',
4-'Domain Predicate Names',
5-'Rule Numbers']),
(nl, tab(8), write(Num), write('.'), tab(4),
write(Item))),
nl, nl, write('Enter the number of a selection> ')),
valid_range(Answer, 1, 5)),
show_1(Answer),
!.
% Execute the selection chosen above by the user.
show_1(1) :-
158
output((nl, nl, tab(34), write('Domain Facts'))),
forall( (domain_head(Head), clause(Head, true)),
(nl, show_clause( (Head :- true)))),
!.
show_1(2) :output((nl, nl, tab(34), write('Domain Rules'))),
forall((domain_head(Head), clause(Head, Body), Body\= true),
(nl, show_clause((Head :- Body)))),
!.
show_1(3) :prompt_cycle((nl, nl,
write('What predicate name?'), nl,
write('Enter a predicate descriptor (Name/Arity or Name)> ')),
valid_domain_pred(PD, _)),
forall((gen_domain_head(PD, Head), clause(Head, Body)),
(nl, show_clause((Head :- Body)))),
!.
show_1(4) :- ·
output((nl, nl, tab(32), write('Domain Predicates'))),
forall((domain_head(Head), functor(Head, Name, Arity)),
output((nl, tab(8), write(Name/ Arity)))),
!.
show_1(5) :output((nl, nl, tab(34), write('Rule Numbers'), nl, nl,
tab(16), write('Motion'), tab(36), write('Number'), nl)),
forall((rule_number(N arne, N urn), padding_needed(52, N arne, Pad)),
output((nl, tab(8), write(Name),
tab(Pad), write(Num)))),
!.
valid_range(N; L, U) :-
L=<N,
N=<U.
% Show the English translation of a domain clause.
show_clause((Head :-true)):-
.,'
prolog_to_ english(Head, English),
output((nl, write_mess(English))).
show_clause((Head :-Body)):numbervars((Head :- Body), 0, _),
explain(O, (Head:- Body)),
!.
% explain/2 is defined in explain.pl
159
% Test for valid domain predicate name.
valid_domain_pred(N arne/ Arity, Head) :gen_domain_head(N arne/ Arity, Head),
!.
valid_domain_pred(Name, Head) :atom(Name),
gen_domain_head(N arne, Head),
!.
valid_domain_pred(N arne, _) :output((nl, nl,
write_mess(['There is no domain predicate called',Name]))),
!, fail.
% Generate domain predicate heads with
% uninstantiated variables.
% N arne and Arity both specified.
gen_domain_head(N arne/ Arity, Head) :-
'.,
functor(Head, Name, Arity),
domain_head(Head).
% Arity not specified Generate all arities of Name.
gen_domain_head(Name, Head) :% Generate arity 1 and arities 2 - 4 on backtracking.
member(N, [1,2,3,4]),
%Construct a Name/N predicate with uninstantiated arguments.
functor(Head, Name, N),
domain_head(Head).
% domain_head/1 and rule_number/2 are defined in rules.pl
% *************************************************************************
% SCRIPT
% Set the name of the script file.
script(File) :script_file(File),
!.
script(File) :retractall( script_file(_)),
assert(script_file(File) ),
160
!.
% *************************************************************************
%WHAT NOW
% Show the user the active context tuple and what action predicates are legal.
what now:top(pending, Context),
inform(current! y_active, Context},
show_options(Context),
!.
inform(currently_active, []) :output((nl, nl,
write('There are no motions currently pending'))),
!.
inform(currently_active, context(State, Motion, Member)) :output((nl,nl, tab(8))),
(State=#->
output(write('The current state is undefined'));
output(write_mess(['The current state is', State]))),
output((nl,nl, tab(8))),
(Motion = # ->
output(write('There is no current Motion'));
output( write_mess(['Motion', Motion,
'is currently active']))),
output((nl,nl, tab(8))),
(Member = # ->
output(write('No one has the floor'));
output(write_mess(['Member', Member, 'has the floor']))),
!.
show_options(Context) :action_options(Context, Options 1),
floor_option(Context, Options2),
append(['makes (motion)' I Options!], Options2, Options),
output((nl, nl, tab(8), write('Possible Actions:'),
forall(member(Action, Options), (nl,tab(20), write( Action))))),
!.
% Show the legal action predicates.
161
action_options(O, []) :- !.
action_options(context(#, _, _), 0) :- !.
action_options(context(put_question, Motion, _), [vote_by_division]) :division_called_for(Motion),
!.
action options(context(put question, Motion, ), [vote]) :- !.
action=options(context(votfng, _, _), [dispose]) :- !.
·
action_options(context(resolved, _, _), [dispose]) :- !.
action_options(context(State,Motion,Mernber), Options) :(decidable_by_chair(Motion) ->Tail= [resolve] I Tail= 0),
action_options 1(context(State,Motion,Mernber), Options 1),
append(Optionsl, Tail, Options),
!.
action_optionsl(context(considering_rnotion, _, _), ['state (question)']):- !.
action_options1(context(debate, _,#),[debates, 'put (question)']):- !.
action_optionsl(context(debate, _, _), [debates]) :- !.
action_optionsl(context(resolving_rnotion, _, #), ['put (question)']) :- !.
action_options 1(context(resolving_motion, _, _), 0).
:floor_option(O, ['obtains (floor)']) :- !.
:floor_option(context(_,_,#), ['obtains (floor)']):- !.
floor_option(context(_,_,_), ['yields (:floor)']).
% **********************************************************************
%WHY
why :- explain.
162
%file name:
%purpose:
%module:
cxt.pl
System Procedures to access the context stack.
SP
% *************************************************************************
% ASSEMBLY STATE
%Find out the current assembly_state.
assembly_state(State) :top(pending, context(State, _, _)).
% **************************************************************************
% HAS FLOOR
% Find out who has the floor.
has_floor(Member) :top(pending, context(_,_, Member)),
% If Member is the null symbol then fail since no one has the floor.
Member\='#'.
% **************************************************************************
%ORDER
% order(Motion, Status) -- Motion is a motion ID and Status tells
% whether Motion is pending (in the pending stack) or active (on top
% of the pending stack).
% Motion is pending if it is anywhere in the pending stack.
order(Motion, pending) :stack(pending, Stack),
member(context(_, Motion,_), Stack),
Motion\='#'.
% Motion is active if at head of pending stack.
order(Motion, active) :top(pending, context(_, Motion,_)),
Motion\=#,
!.
% **************************************************************************
% POP
163
% Pop a stack.
pop(StkName, Val) :retract(stack(StkName, [Vall Rest])),
assert(stack(StkName, Rest)),
!.
pop(StkName, 0) :stack(StkName, 0).
% **************************************************************************
% PUSH
% Push an item onto a stack.
push(StkName, Item) :retract(stack(StkName, Stack)),
assert(stack(StkName, [Item I Stack])).
% **************************************************************************
% TOP
% Find out what's on top of a stack.
top(StkName, Item) :stack(StkName, [Item I_]),
!.
top(StkName, []) :stack(StkName, 0).
% **************************************************************************
% UPDATE_FLOOR
%Update member who has the floor in top context of pending stack.
% pending stack is not empty.
update_fioor(Member) :retract(stack(pending, context(State,Motion,_).Stack)),
I.,
assert(stack(pending, context(State,Motion,Member).Stack)).
% pending stack is empty.
% No state or motion (make them both null '#').
update_fioor(Member) :stack(pending, 0),
164
.,I
push(pending, context(#, #, Member)).
% **************************************************************************
% UPDA1E_PENDING
% Push motion on pending stack.
% r19 and r19a allow the previous speaker to continue after they are
%resolved. Just push them onto stack.
update_pending(Member, MID:rl9a) :!,
push(pending, context(considering_motion, MID:r19a, Member)).
update_pending(Member, MID:r19) :-
.,1
push (pending, context(considering_motion, MID:rl9, Member)).
%No other motion is pending. Change the active context.
update_pending(Member, Motion) :retract(stack(pending, context(#,#,_).Stack)),
.,
I
assert(stack(pending, context(considering_motion,Motion,Member).Stack) ).
% Some other motion is already pending, push new motion on top of stack.
% Member who had floor is forgotten, remove him/her from previous context
% (replace with #, the null symbol).
update_pending (Member, Motion) :retract(stack(pending, context(OldSt, OldMot, _).Stack)),
.,
I
assert(stack(pending,
[context(considering_motion,Motion,Member),
context(OldSt,OldMot,#) I
Stack])).
% Pending stack is empty.
update_pending(Member, Motion) :stack(pending, []),
.,'
push(pending, context(considering_motion, Motion, Member)).
% **************************************************************************
% UPDATE_STATE
%Update state in top context of pending stack.
% Pending stack is nonempty.
165
update_state(State) :retract(stack(pending, context(_, Motion, Member).Stack)),
.,'
assert(stack(pending, context(State, Motion, Member).Stack)).
%Pending stack is empty. Create a new context and push on stack.
update state(State) :stack(pending, []),
.,'
push(pending, context(State, #, #)).
166
% file name:
% purpose:
% module:
explain.pl
Procedures for explanations.
SP
% *************************************************************************
% EXPLAIN
% Explain why a state update was accepted or rejected.
% Set up the explanation.
explain:% Find the top level goal Head.
pt(_, (Head :- _)),
.,I
prolog_to_english(Head, English),
output((nl, write(' Explanation of: '), write_mess(English), nl)),
% Explain all proof-tree nodes (pt/2) in order.
forall(pt(L, Item), explain(L, Item)).
% If there is no top level goal then tell the user.
explain :output((nl,nl, write('There is nothing to explain'))).
explain(_, line_feed) :-
.,1
output(nl).
% Facts need no further explanation.
explain(L, (not Goal :- true)) :(Goal = (A,B); Goal = (A;B)),
.,I
list_conjunction(not Goal, L),
output(write(' is true')).
explain(L, (Head :- true)) :-
.,I
prolog_to_english(Head, English),
output((nl, tab(L), write('<'), write_mess(English),
write('> is true'))).
% Explain a rule.
explain(L, (Head:- Body)) :-
.,1
prolog_to_english(Head, English),
i
% KNAP system predicates are not explained so delete ithem from the
% body of the rule.
·i
remove_knap_predicates(Body, Bodyl),
output((nl, tab(L), write('<'), write_mess(English),i write('> if:'))),
167
(Bodyl = true ->
% Body consisted exclusively of one or more knap system predicates.
output(write(' system procedure'))
I
% Body has other non-system predicates in it.
%Display each conjunct of the body.
plus(L, 4, L2),
list_conjunction(Bodyl, L2),
output(write('.'))),
!.
% Display a failed goal.
explain(L, failed(Goal)) :prolog_to_english(Goal, English),
output((nl, tab(L), write('<'), write_mess(English ),
write('> is false'))),
!.
% *************************************************************************
% KNAP_PREDICATE
% These predicates are hidden from the user during explanations.
% once/1 and not/1 are system predicates but are not knap_predicates.
knap_predicate(forall(_,_)) :- !, fail.
knap_predicate(not(_)) :- !, fail.
knap_predicate(once(_)) :- !, fail.
knap_predicate(Pred) :system_predicate(Pred), !.
knap_predicate( add_pending_motion(_,_)).
knap_predicate( ask_about_motion(_,_,_)).
knap_predicate( ask_about_qop(_)).
knap_predicate(carry_out(_•..:.,_)).
knap_predicate(conditional(_,_,_)).
knap_predicate(inform(_,_) ).
knap_predicate(output(_)).
knap_predicate( time_sequence(_)).
knap_predicate(top(_,_)).
knap_predicate(update_floor(_)).
knap_predicate(update_pending(_,_)).
knap_predicate(update_state(_)).
knap_predicate(vote_on(_)).
% *************************************************************************
% LIST CONJUNCTION
% Display the conjuncts of a rule body.
168
% list_conjunction(Term, Indent) -- Term is the term to be displayed.
% Indent is the number of spaces to indent the output
% Get rid of "true" at end of conjunction.
list_conjunction((A,true), Indent) :-
.,1
list_conjunction( A, Indent).
% Regular conjunction.
list_conjunction((A,B), Indent) :!,
list_conjunction( A, Indent),
output( write(' AND')),
list_conjunction(B, Indent).
% Disjunction.
list_conjunction((A;B), Indent) :1
.,
output((nl, tab(Indent), write('('))),
list_disjunction((A;B), Indent),
output((nl, tab(Indent), write(')'))).
%Don't display "true" in middle of conjunction.
list_conjunction(true, _) :- !.
% Negated conjunction.
list_conjunction(not (A,B), Indent) :-
'.,
output((nl, tab(Indent), write('It is false that:'),
nl, tab(Indent), write('('))),
plus(Indent,2,Indent2),
list_conjunction((A,B), Indent2),
output((nl, tab(Indent), write(')'))).
% Negated disjunction.
list_conjunction(not (A;B), Indent) :-
.,1
output((nl, tab(Indent), write('It is false that:'),
nl, tab(Indent), write('('))),
plus(Indent,2,Indent2),
list_disjunction((A;B), Indent2),
output((nl, tab(Indent), write(')'))).
%Ignore Prolog predicate once/1 and display Goal.
list_conjunction(once(Goal), Indent) :-
.,
'
list_conjunction(Goal, Indent).
% A single predicate.
list_conjunction(Goal, Indent) :prolog_to_english(Goal, TransGoal),
output((nl, tab(Indent), write_mess(TransGoal))).
% *************************************************************************
% LIST DISWNCTION
169
% List the predicates of a disjunction.
% Normal disjunction.
list_disjunction((A;B), Indent) :-
.,1
prolog to english(A, TransA),
output((nl, tab(Indent), write_mess(TransA), write(' OR'))),
list_disjunction(B, Indent).
% A conjunction found within a disjunction.
list_disjunction((A,B), Indent) :-
.,1
list_conjunction((A,B), Indent).
% Goal is a single predicate.
list_disjunction( Goal, Indent) :list_conjunction(Goal, Indent).
% *************************************************************************
% PROCEDURE
% These predicates are mentioned as goals but the ERI calls them directly
% and does not explain them any further.
procedure(askable(_) ).
procedure(business_since_last_moved(_)).
procedure(business_transacted(_,_)).
procedure(forall(_,_)).
procedure(has_floor(_)).
procedure(input_decision(_, _)).
procedure(last_occurrence(_, _) ).
procedure( making_motion(_,_)).
procedure( may_have_floor(_)).
procedure(motion_class(_, _)).
procedure(order(_, _)).
% *************************************************************************
% REMOVE- KNAP- PREDICATES
%Delete all KNAP system predicates from a conjunction.
% First term in conjunction is a disjunction.
remove_knap_predicates(((A;B),C), (NewAB, NewC)) :-
.,1
remove_knap_predicates((A;B ), New AB),
remove_knap_predicates(C, NewC).
170
% Conjunction
remove_knap_predicates((A,B), NewB) :knap_predicate(A),
..
remove_knap_predicates(B. NewB).
I
remove_knap_predicates((A,B). (A,NewB)) :-
'..
.
remove_knap_predicates(B, NewB).
% Disjunction
remove_knap_predicates((A;B), (New A;NewB)) :-
'..
remove_knap_predicates(A, NewA),
remove_knap_predicates(B. NewB).
% Replace single knap predicates with "true".
remove_knap_predicates(Pred, true):knap_predicate(Pred),
!.
% Leave all other predicates unchanged.
remove_knap_predicates(Pred, Pred).
171
%file name:
%purpose:
%module:
io.pl
General input/output routines
SP
% *************************************************************************
% APPEND TO FILE
% Output to the end of a file instead of overwriting it
% append_to_file(DO, File) -- DO is the conjunction ofProlog
% output commands that will cause File to be written to.
% If script file is "none" then do nothing.
append_to_file(_, none) :- !.
append_to_file(OO, File) :% Find out the old output file.
telling( OLD),
% Switch output stream to File.
append(File),
DO,
% Switch back to old output file.
tell( OLD),
!.
% **************************************************************************
% OUTPUT
% The general outputter routine.
% Writes to the script file.
% DO is a conjunction of Prolog output commands.
output(DO) :DO,
script_file( Script),
append_to_file(DO, Script),
!.
% **************************************************************************
% PROMPT_CYCLE
%Output a prompt and read a response from the user.
% prompt_cycle(Prog Test) -% Prog is the output statement that will prompt the user.
% Test is a term whose first argument will be unified with the user's response.
% If Test succeeds then accept the response and exit. Otherwise fail back
172
% and prompt the user again for new input
prompt_cycle(Prog, Test) :repeat,
output(Prog),
read_and_echo(Input),
arg{l, Test, Input),
Test,
!.
% **************************************************************************
% READ_AND_ECHO
% Read in a term and echo it to the script file.
read_and_echo(Term) :read(Term),
script_file(Script),
append_to_file(write(Term), Script),
!.
% **************************************************************************
% WRITE LIST
% write_list(List, Action) -% Write out a list of terms List, execute Action after each term is output.
write_list([], _).
write_list([A], _) :write(A),
!.
write_list([A I B], Do) :write(A),
Do,
write_list(B, Do),
!.
% **************************************************************************
% WRITE_MESS
% Write out the terms in List, write ' ' after each term is output
write_mess(List) :write_list(List, write(' ')),
173
!.
174
%purpose:
%module:
Translation of PKRL to English
SP
% ************************************************************.*************
% NUMBEREDVAR
% See if a term is a variable that has gone through numbervars/3
numberedvar(X) :nonvar(X), functor(X,VF,l), numbervars(V,O,_), functor(V,VF,l).
% *************************************************************************
% PROLOG TO ENGLISH
% Translate a PKRL predicate to English.
prolog_to_english(Term, Eng) :numbervars(Term, 0, _),
p_to_e(Term, Eng),
!.
% *************************************************************************
% P TOE
%. English string translations of PKRL predicates.
% Conjunction.
p_to_e((A, B), Eng)
p_to_e(A, EngA),
p_to_e(B, EngB),
append(EngA, [and I EngB], Eng),
!.
% Disjunction.
p_to_e((A; B), Eng)
p_to_e(A, EngA),
p_to_e(B, EngB),
append(EngA, [or I EngB], Eng),
!.
p to e(amendable(Motion),
[motion,Motion,'is amendable']) :- !.
p_to_e( applicable_to(Motion, ApplyTo ),
175
J.
[motion.Motion,'may be apptfed to motion',ApplyTo]) :- !.
p_to_e(applies_ to(Motion,ApplyTo ),
[motion.Motion,'applies to motion' ,ApplyTo]) :- !.
p_to_e(askable(Goal), Eng) :p_to_e(Goal, Eng), !.
p_to_e(assembly_state(State),
['the assembly state is' ,State]) :- !.
p_to_e(business_since_Iast_moved(_:RNum),
['business has occurred since a motion of type' ,RNum,
'was last moved']) :- !.
p_to_e(business_ transacted(T 1,T2),
['business occurred between time' ,Tl,'and time' ,T2]) :- !.
p _to_e(class_status( Class, pending),
['there is a' ,Class,' motion pending']) :- !.
p_to_e(debatable(Motion),
[motion.Motion,'is debatable']) :- !.
p_to_e(debates (Member, Motion),
[member,Member,'may debate motion' .Motion]) :- !.
p_to_e(decidable_by_chair(Motion),
[motion.Motion,'may be decided by the Chairman']) :- !.
p_to_e(decided(chair, Motion),
[the,'Chairman' ,'decided motion' ,Motion]) :- !.
p_to_e(dispose(Motion),
[motion,Motion,'may be disposed of]):- !.
p_to_e(division_called_for(Motion ),
['a division of the assembly has been called for on motion',
Motion]) :- !.
p_to_e(eligible_for_consideration(Motion, _),
[motion,Motion,'is eligible for consideration']) :- !.
p_to_e(eligible_for_consideration(Motion,_._,_), Eng) :p_to_e(eligible_for_consideration(Motion,_), Eng), !.
p_to_e(false(Goal), Eng) :p_to_e(not(Goal), Eng), !.
p_to_e(forall(A, B), Eng):-
r .
176
p_to_e(A, EngA),
p_to_e(B, EngB),
append([wheneveriEngA], [','IEngB], Eng),
!.
p_to_e(has_fl~r(Member),
['someone has the floor']) :numberedvar(Member), !.
p_to_e(has _floor(Member),
[member,Member,'has the floor']) :- !.
p_to_e(in_order(Motion, _, .J,
[motion,Motion,'is in order']) :- !.
p_to_e(input_decision (Motion, Decide),
['the Chair"s decision on motion',Motion,is,Decide]) :- !.
p_to_e(irreversible(Motion),
['action has been taken on' ,Motion,
'that cannot be undone']) :- !.
p_to_e(log(A, B), English) :translog(A, B, English), !.
p to e(makes(Member, RNum),
[member,Member,' may make a motion of type' ,RNum]) :- !.
p_to_e(makes(Member, Motion, none),
[member,Member,'may make motion',Motion]) :- !.
p_to_e(makes(Member, Motion, ApplyTo),
[member,Member,'may make motion' ,Motion,' which applies to',
motion,ApplyTo]) :- !.
p_to_e(mak:ing_motion(Member, RNum),
[member,Member,'is making a motion of type', RNum]) :- !.
p_to_e(may_have_floor(Member),
[member,Member,'may have the floor']) :- !.
p_to_e(motion_ class(Motion, Class),
['motion number' ,Motion,' is a' ,Class,motion]) :- !.
p_to_e(needed_to_pass(Motion, majority),
[motion,Motion,'requires a majority to pass']) :- !.
p_to_e(needed_to_pass(Motion, Needed),
[motion,Motion,'requires a' ,Needed,' majority to pass']) :- !.
177
p to e(not Goal,
['it is false that'
p _to_e(Goal, GoalEng), !.
I GoalEng]) :-
p _to_e(notice_given(Motion),
['previous notice of the vote on',Motion,'has been given']):-!.
p_to_e(obtains(Member),
[member,Member,'may obtain the floor']) :- !.
p_to_e(once(Goal), Eng):p_to_e(Goal, Eng), !.
p_to_e(order(Motion, Status),
['some motion',Motion,is,Status]) :numberedvar(Motion), !.
p _to_e(order(MID:RNum, Status),
['a motion of type',RNum,is, Status]):numberedvar(MID), !.
p_to_e(order(Motion, Status),
[motion,Motion,is,Status]) :- !.
p _to_e(orderly_introduction(Motion, Member),
[motion,Motion,'was legally introduced']) :- !.
p _to_e(putq(Motion),
[motion,Motion,'may be put to the assembly']) :- !.
p_to_e(relates_to(MID, List), Eng):append([motion,MID,'relates to'], List, Eng), !.
p to e(resolve(Motion),
[motion,Motion,'is resolved']) :- !.
p to e(seconded(Motion),
[motion,Motion,'has been seconded']) :- !.
p _to_e(special_order_scheduled(MID),
['a special order is scheduled']) :- !.
p to e(state(Motion),
[motion,Motion,'may be stated to the assembly']) :- !.
p to e(subject(Motion,multiple ),
- [motion,Motion,'consists of multiple subjects']) :- !.
p _to_e(tak:en_up_ by_committee(Apply2),
['a committee has already taken up motion' ,Apply2]) :- !.
178
p_to_e( tentative_result(Motion, _,_),
[motion,Motion,'has been tentatively resolved']) :- !.
p_to_e(urgency(MID, immediate),
[motion,MID,'is of immediate urgency']) :~ !.
p_to_e(variation_from_order(MID),
['there is a variation from the order of business']) :- !.
p_to_e(vote(Motion),
['the assembly may vote on motion' ,Motion]) :- !.
p_to_e(vote_by_division(Motion),
[motion,Motion,'may be voted on by division']) :- !.
p_to_e(voted_ against(MemiD, ApplyTo),
[member,MemiD,'voted against motion' ,ApplyTo]) :- !.
p_to_e(voted_for(MemiD, ApplyTo),
[member,MemiD,'voted for motion',ApplyTo]) :- !.
p_to_e( voting_method(Motion, Method),
['the method of voting for motion',Motion,was,Method]) :- !.
p_to_e(yields(Member),
[member,Member,'may yield the floor']) :- !.
% Catch all, Pred is left untranslated.
p_to_e(Pred, [Pred]).
% *************************************************************************
% TRANSLATE AND NEGATE
-
-
translate_and_negate(Goal, Trans) :negate(Goal, Neg),
prolog_to_english(Neg, Trans),
!.
9b *************************************************************************
9b TRANSLOG
9b Translate the arguments of a log entry into English.
translog(event(debated, MemiD, Motion), Tag,
[member,MemiD,'debated motion' ,Motion,' at time' ,Tag]) :- !.
179
translog(event(in_order, Motion), Tag,
[motion,Motion,'became in order at time',Tag]) :- !.
trans log(event( made_motion, Me miD, Motion), Tag,
[member,MemiD,'made motion',Motion,'at time',Tag]) :- !.
translog(event(obtained_fioor, MemiD), Tag,
[member,MemiD,'obtained the floor at time',Tag]) :- !.
translog(event{put_question, Motion), Tag,
[motion,Motion,'was put to the assembly at time' ,Tag]) :- !.
translog(event(stated, Motion), Tag,
[motion,Motion,'was stated at time' ,Tag]) :- !.
translog(resolved(Motion,none,Result), Tag,
[motion,Motion,Result,'at time' ,Tag]) :- !.
translog(resolved(Motion,ApplyTo,Result), Tag,
[motion,Motion,' applied to' ,ApplyTo,Result,' at time', Tag]).
180
Appendix B
Sample Session Transcript
181
KNAP
TilE KNOWLEDGE BASED AUTOMATED PARLIAMENTARIAN
READY> show
What would you like to see?
1.
2.
3.
4.
5.
Domain Facts
Domain Rules
Domain Predicate
Domain Predicate Names
Rule Numbers
Enter the number of a selection > 5
Rule Numbers
Motion
Number
Fix Time to Adjourn
Adjourn
Recess
Question of Privilege
Call for Orders of the Day
Appeal
Question of Order
Suspension of the Rules
Objection to Consideration of a Question
Division of a Question
Division of Assembly
Motions Relating to Voting
Method of Nomination
Close Nominations
Reopen Nominations
Parliamentary Inquiry
Withdraw a Motion
Modify a Motion
Reading Papers
Lay on the Table
Previous Question
Lfmit or Extend Debate
Postpone Definitely
Commit or Refer
Amend
Postpone Indefinitely
Take from Table
Reconsider
r16
r17
r18
r19
r20
r21a
r21q
r22
r23
r24
r25div
r25
r26meth
r26close
r26reop
r27info
r27cw
r27cm
r27d
r28
r29
r30
r31
r32
r33
r34
r35
r36
p •
182
Rescind, Repeal, or Annul
Main Motion
r37
main
READY> bill obtains
Action accepted
READY> bill makes main
The ID for this new motion is 1
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n.') > n
Is it true that
motion l:main has been seconded?
[yes. I no.] >no
ILLEGAL ACTION
it is
it is
it is
it is
it is
false
false
false
false
false
that
that
that
that
that
some motion A is pending
motion 1:main has been seconded
motion l:main is in order
member bill may make motion l:main
member bill may make a motion of type main
READY> why
Explanation of: member bill may make a motion of type main
<member bill may make a motion of type main> if:
member bill may make motion A which applies to motion B.
<member bill may make motion l:main> if:
motion l:main is in order.
<motion l:main is in order> if:
it is false that some motion A is pending AND
member bill may have the floor AND
motion l:main has been seconded.
<Some motion A is pending> is false
<it is false that some motion A is pending> is true
<member bill may have the floor> is true
<motion l:main has been seconded> is false
<motion l:main is in order> is false
<member bill may make motion l:main> is false
<member bill may make a motion of type main> is false
183
READY> mary makes main
The ID for this new motion is 2
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n.') > n
ILLEGAL ACTION
it
it
it
it
it
is
is
is
is
is
false
false
false
false
false
that
that
that
that
that
some motion A is pending
member mary may have the floor
motion 2:main is in order
member mary may make motion 2:main
member mary may make a motion of type main
READY> bill yields
Action accepted
READY> mary makes main
The ID for this new motion is 3
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n. ') > n
Is it true that
motion 3:main has been seconded?
[yes. I no.] > y
Action accepted
READY> state 3:main
Action accepted
READY> mary debates 3:main
Action accepted
READY> john makes r21q
The ID for this new motion is 4
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n.') > n
Action accepted
184
READY> explain
Explanation of: member john may make a motion of type r21q
<member john may make a motion of type r21q> if:
member john may make motion A which applies to motion B.
<member john may make motion 4:r21q> if:
motion 4:r21q is in order.
<motion 4:r21q is in order> if:
it is false that there is a privileged motion pending.
<there is a privileged motion pending> if:
a motion of type B is pending AND
motion number B is a privileged motion.
<motion 3:main is pending> is true
<motion number main is a privileged motion> is false
<there is a privileged motion pending> is false
<it is false that there is a privileged motion pending> is true
<motion 4:r21q is in order> is true
<member john may make motion 4:r21q> is true
<member john may make a motion of type r21q> is true
READY> pending
Motions currently pending
State
considering_motion
debate
Motion
4:r21q
3:main
Has Floor
john
none
READY> john yields
Action accepted
READY> phil makes r31
The ID for this new motion is 5
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n.') > 3:main
ILLEGAL ACTION
it is false
it is false
there is a
it is false
it is false
that motion number r21q is a privileged motion
that there is a privileged motion pending
incidental motion pending
that motion 5:r31 is in order
that member phil may make motion 5:r31 which applies to motion 3:main
185
it is false that member phil may make a motion of type r31
READY> why
Explanation of: member phil may make a motion of type r31
<member phil may make a motion of type r31> if:
member phil may make motion A which applies to motion B.
<member phil may make motion 5:r31 which applies to motion 3:main> if:
motion 5:r31 is in order.
<motion 5:r31 is in order> if:
member phil may have the floor AND
motion 3:main is pending AND
it is false that there is a privileged motion pending AND
it is false that there is a incidental motion pending AND
it is false that a motion of type r28 is pending AND
it is false that a motion of type r29 is pending AND
it is false that a motion of type r30 is pending AND
motion 5:r31 has been seconded.
<member phil may have the floor> is true
<motion 3:main is pending> is true
<there is a privileged motion pending> if:
a motion of type B is pending AND
motion number B is a privileged motion.
<motion 4:r21q is pending> is true
<motion number r21q is a privileged motion> is false
<there is a privileged motion pending> is false
<it is false that there is a privileged motion pending> is true
·<there is a incidental motion pending> if:
a motion of type B is pending AND
motion number B is a incidental motion.
<motion 4:r21q is pending> is true
<motion number r21q is a incidental motion> is true
<there is a incidental motion pending> is true
<it is false that there is a incidental motion pending> is false
<motion 5:r31 is in order> is false
<member phil may make motion 5:r31 which applies to motion 3:main> is false
<member phil may make a motion of type r31> is false
READY> what now
The current state is considering_motion
Motion 4:r21q is currently active
186
No one has the floor
Possible Actions:
makes (motion)
state (question)
resolve
obtains (floor)
READY> jane makes r16
The ID for this new motion is 6
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n. ') > n
Is it true that
motion 6:r16 has been seconded?
[yes. I no.] > y
Action accepted
READY> state 6:r16
Action accepted
READY> pending
Motions currently pending
State
Motion
resolving_motion
considering_motion
debate
6:r16
4:r21q
3:main
Has Floor
jane
none
none
READY> jane debates 6:r16
ILLEGAL ACTION
it is
it is
it is
it is
false
false
false
false
that
that
that
that
whenever some motion A is pending , A=6:r16
motion number 6:r16 is a main motion
motion 6:r16 is debatable
member jane may debate motion 6:r16
READY> explain
Explanation of: member jane may debate motion 6:r16
<member jane may debate motion 6:r16> if:
motion 6:r16 is active AND
motion 6:r16 is debatable AND
187
the assembly state is debate AND
member jane has the floor.
<motion 6:r16 is active> is true
<motion 6:r16 is debatable> if:
whenever some motion A is pending, A=6:r16.
<whenever some motion A is pending , A=6:r16> is false
<motion 6:r16 is debatable> if:
motion number 6:r16 is a main motion.
<motion number 6:r16 is a main motion> is false
<motion 6:r16 is debatable> is false
<member jane may debate motion 6:r16> is false
READY> what now
The current state is resolving_motion
Motion 6:r16 is currently active
Member jane has the floor
Possible Actions:
makes (motion)
yields (floor)
READY> jane yields
Action accepted
READY> what now
The current state is resolving_motion
Motion 6:r16 is currently active
No one has the floor
Possible Actions:
makes (motion)
put (question)
obtains (floor)
READY> put 6:r16
Action accepted
READY> vote 6:r16
188
Enter the number of votes in favor of motion 6:r16
>3
Enter the number of votes against motion 6:r16
>8
Enter the number of abstentions
>2
The result of the vote on motion 6:r16 : failed
Action accepted
READY> dispose 6:r16
Done
The current state is considering_ motion
Motion 4:r21q is currently active
No one has the floor
Action accepted
READY> pending
Motions currently pending
State
Motion
4:r21q
considering_motion
3:main
debate
READY> resolve 4:r21q
What is the Chair's decision on motion 4:r21q?
[pass. 1 fail.] > pass
Action accepted
READY> what now
The current state is resolved
Motion 4:r21q is currently active
No one has the floor
Possible Actions:
makes (motion)
dispose
Has Floor
none
none
189
obtains (floor)
READY> dispose 4:r21q
Done
The current state is debate
Motion 3:main is currently active
No one has the floor
Action accepted
READY> sam obtains
Action accepted
READY> sam debates 3:main
Action accepted
READY> sam yields
Action accepted
READY> tim obtains
Action accepted
READY> tim makes r33
The ID for this new motion is 7
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n.') > 3:main
Is it true that
motion 7:r33 has been seconded?
[yes. I no.] > y
Action accepted
READY> pending
Motions currently pending
State
Motion
considering_motion
7:r33
debate
3:main
Has Floor
tim
none
190
READY> state 7:r33
Action accepted
READY> tim yields
Action accepted
READY> jim makes r28
The ID for this new motion is 8
To which motion will this new motion apply?
Enter the motion ID (if none enter 'n.') > 3:main
Is it true that
motion 8:r28 has been seconded?
[yes. I no.] > y
Action accepted
READY> why
Explanation of: member jim may make a motion of type r28
<member jim may make a motion of type r28> if:
member jim may make motion A which applies to motion B.
<member jim may make motion 8:r28 which applies to motion 3:main> if:
motion 8:r28 is in order.
<motion 8:r28 is in order> if:
member jim may have the floor AND
(
motion number 3:main is a privileged motion OR
it is false that there is a privileged motion pending
)AND
motion 3:main is pending AND
motion 8:r28 is eligible for consideration AND
motion 8:r28 may be applied to motion 3:main AND
motion 8:r28 has been seconded.
<member jim may have the floor> is true
<motion number 3:main is a privileged motion> is false
<there is a privileged motion pending> if:
a motion of type B is pending AND
motion number B is a privileged motion.
<motion 7:r33 is pending> is true
<motion number r33 is a privileged motion> is false
<there is a privileged motion pending> is false
191
<it is false that there is a privileged motion pending> is true
<motion 3:main is pending> is true
<motion 8:r28 is eligible for consideration> if:
it is false that it is false that motion 8:r28 is eligible
for consideration.
<it is false that motion 8:r28 is eligible for consideration> if:
motion A:r28 applied to 3:main failed at time B AND
member C made motion 8:r28 at time D AND
it is false that business occurred between time B and
timeD AND
it is false that motion 8:r28 is of immediate urgency.
<motion A:r28 applied to 3:main failed at time B> is false
<it is false that motion 8:r28 is eligible for consideration> if:
motion A:r35 applied to 3:main passed at time B AND
member C made motion 8:r28 at time D AND
it is false that business occurred between time B and
timeD AND
it is false that motion 8:r28 is of immediate urgency.
<motion A:r35 applied to 3:main passed at time B> is false
<it is false that motion 8:r28 is eligible for consideration>
is false
<it is false that it is false that motion 8:r28 is eligible
for consideration> is true
<motion 8:r28 is eligible for consideration> is true
<motion 8:r28 may be applied to motion 3:main> if:
motion number 3:main is a main motion.
<motion number 3:main is a main motion> is true
<motion 8:r28 may be applied to motion 3:main> is true
<motion 8:r28 has been seconded> is true
<motion 8:r28 is in order> is true
<member jim may make motion 8:r28 which applies to motion 3:main> is true
<member jim may make a motion of type r28> is true
READY> pending
Motions currently pending
State
Motion
considering_motion
8:r28
7:r33
debate
3:main
debate
READY> state 8:r28
Action accepted
Has Floor
jim
none
none
192
READY> jim yields
Action accepted
READY> put 8:r28
Action accepted
READY> vote 8:r28
Enter the number of votes in favor of motion 8:r28
>10
Enter the number of votes against motion 8:r28
>2
Enter the number of abstentions
>1
The result of the vote on motion 8:r28 applied to motion 3:main :passed
Action accepted
READY> dispose 8:r28
Motion 3:main and all motions that adhere to it have been laid on the table.
Done
There are no motions currently pending
Action accepted
READY> pending
No motions currently pending
READY> halt
Minutes of Session
member bill obtained the floor at time 1
member bill made motion l:main at time 2
member mary made motion 2:main at time 3
member inary made motion 3:main at time 4
motion 3:main became in order at time 5
motion 3:main was stated at time 6
member mary debated motion 3:main at time 7
member john made motion 4:r21q at time 8
motion 4:r21q became in order at time 9
member phil made motion 5:r31 at time 10
member jane made motion 6:r16 at time 11
193
motion 6:r16 became in order at time 12
motion 6:r16 was stated at time 13
motion 6:r16 was put to the assembly at time 14
motion 6:r16 failed at time 15
motion 4:r21q passed at time 16
member sam obtained the floor at time 17
member sam debated motion 3:main at time 18
member tim obtained the floor at time 19
member tim made motion 7:r33 at time 20
motion 7:r33 became in order at time 21
motion 7:r33 was stated at time 22
member jim made motion 8:r28 at time 23
motion 8:r28 became in order at time 24
motion 8:r28 was stated at time 25
motion 8:r28 was put to the assembly at time 26
motion 8:r28 applied to 3:main passed at time 27
KNAP Session Completed
© Copyright 2025 Paperzz