    Not long ago, George Hageman posted an inference engine written
in C to the net.  Infer is a re-write of "rulecomp" and "inference".

    My goals in the rewrite were: remove restrictions, centralize I/O,
simplify, enhance, and (if I may coin a word) Unixfy.

REMOVING RESTRICTIONS:
    Well, the best way to do that was to malloc everything.  The concept
of "rule" has changed from value-string pair to a group of ANTECEDENTS
and a group of CONSEQUENTS.  Thus, with the original 500 rules, there
could be a max of 500 ANTs and CONs with 1 rule used to seperate each.
It is roughly one rule per line, plus overhead.  With the new, 1000
rules is 1000 statement groups.  Beyond that, there are no limitations
on the number of strings.  The maximum string size is 512 - length of
keyword - 1 for the space.

    The other restriction removed is the need for a seperate compiler,
and the intermediate file that it produces.  I realize that one
goal of Mr. Hageman was to keep the two modules seperate, and therefore
smaller, but I'd rather keep the two together and eliminate the extra
file.  This also simplifies the expert system which wishes to build
it's own rule-set, and run the engine on it.

CENTRALIZING I/O:
    In both originals, input and output were spread among all source
files.  To effect a change, one had to discover all locations that
performed the operation.  For example, to make "rulecomp" quiet, I
had to change lines in three different source files.

SIMPLIFYING:
    Where there were two programs, now there is one.  There
are no more stacks (except for the crude "WHY" interface).  I/O all
happens in one place for each operation (not true for output).
There was a large amount of code duplication in the original that I
bundled into a function or two, and the six different types, along with
the 18 keyword representations, have become four flags which may be
ORed together.

ENHANCING:
    There is now a rather crude "Why" processor, and the code can
detect and display circular logic rules.  The strings to be run
by the system are executed via system(3).  Although this requires
the overhead of a shell, the advantages are great.  One can use
environment variables and redirection, for example.

UNIXFING:
    The concept of quiet and verbose has already been mentioned,
and the optional argument to make it verbose has been added.  Blank
lines are not present in the output, and upper/lower case is used
extensivly.  Error returns from system and library calls are checked,
and apropriate messages are displayed.  The exit value from a program
is more in line with tradition: 0 = TRUE, !0 = FALSE.  Thus, one can
call, for example, grep(1) and properly determine the truth-value.

    As far as size is concerned, infer is smaller than inference,
realizing of course that infer mallocs the world, while inference
has static data already declared.

    I've been unable to measure any noticable difference in the speed
of the programs, both of which have user time < 1 second.  Of course
I'd like to say mine is faster, but that would be fibbing.

    I had read somewhere that only a language traditionally suited for
AI was able to handle things like "inference".  Thanks, Mr. Hageman,
for dissolving that myth.

    I've gained some valuable knowledge from this rewrite.  Thanks,
again, Mr. Hageman, for sharing your code with me.

    I now place this program in the public domain, with no
restrictions as to its use.  If bugs are found (I'm sure some will
be) let me know, so I can incorporate them into my "official"
version.  Use this program freely, but at your own risk.  One should
also not sell this program for profit; it was freely given, therefore,
freely give.

Daniel S. Cox
ihnp4!akgua!itm!danny
