Rule-Based Shipping Advisor Sample

Shipping notes on how to build an embedded rule-based system in Prolog.

Design issues -

One of the major first issues is deciding whether or not the application will make use of custom extensions to
the Prolog language.

Any host language application can query the Prolog rule base, assert and retract facts, get answers back, but
the host program is in control.  Prolog only responds.

Using C/C++, the developer can create custom extensions to Prolog that allow Prolog to respond back to the application.

The simplest example is use of a built-in messagebox predicate that Prolog can use to query the user.

Development steps -

Come up with some simple rules and getting it working in the interpreter.

Playing with the ideas starts to give shape to the application.

Write a Prolog front-end that simulates the interaction with the system that the host program will have.  This
allows testing and debugging to proceed in the Prolog interactive environment.

Example - the shipping application will be embedded in VB, so interaction will be through assert facts, gathered
from the VB front end.  A main routine simulates this by gathering inputs and calling the main predicates.

Start simple - examples from shipper - try this and test it, if there's bugs, then use the debugger to trace the
output, understand the flow of control and the interaction of the rules for a simple case.

main :-
  get_inputs,
  get_options.

get_options :-
  option(Shipper, Service, Cost, Delivery),
  write(Shipper:Service:Cost:Delivery), nl,
  fail.
get_options.  

get_inputs :-
  prompt(weight, $What is the weight? $),
  prompt(type, $What type of package (brochure, package)? $),
  prompt(destination, $What is the destination? $).

prompt(Attr, Prompt) :-
  write(Prompt),
  read_string(Str),
  string_term(Str, Val),
  retractall(known(Attr, _)),
  assert(known(Attr, Val)).

% Rules callable from VB

option(Shipper, Service, Cost, Delivery) :-
  shipper(Shipper, Service, Cost, Delivery).

shipper('USMail', 'First Class', Cost, 'One or two days') :-
  known(weight, W),
  known(destination, D),
  cost_usmail(W, D, Cost).

cost_usmail(W, 'USA', 32) :-
  W =< 1.
cost_usmail(W, 'USA', X) :-
  X is 32 + 23 * (W - 1).
Design points, its often useful to keep the information being reasoned over separate from the rules and data
of the expert system.

In this case information is represented as simple attribute: value pairs, such as weight:3.  They are stored in a
Prolog fact, known(Attr,Val).

Utility predicates are written to maintain the information. They can grow complex, to full frame-based systems.