[MUD-Dev] OpenCyc, design implications of ontological systems ?

Robert Zubek rob at cs.northwestern.edu
Fri May 3 12:09:40 New Zealand Standard Time 2002

Hey Bruce,

My apologies for the delay - I was out of town for a while.
But, back to the discussion... :)


> Some of this thinking on my part sprung from an observation of
> patterns in code that I was writing.  I would find myself writing
> small methods here and there to determine whether or not a given
> object could do something.  The bird flying example is good
> enough. Can the bird fly? The method to determine that might be
> overriden on various objects (even non-bird objects) to make that
> determination. At that point, it becomes far simpler to have a
> logic system/knowledge base that can be queried. I'm not sure that
> I want to (or see the need to) model everything within the logic
> system.

So, let me attempt to recap a bit. It seems like the logic engine
would do at least two things for the world:

  1. Make it easy to define the object hierarchy 

  2. Provide better function dispatching, a la predicate dispatch

In particular:

  1. World definition

    It would be easier to define the world using predicate logic,
    such as:

      (implies (and (isa ?X bird)
                    (not (isa ?X ostrich)))
               (canfly ?X))

    ...rather than having to manually set up relations and
    attributes all over the object hierarchy.

  2. Function dispatching

    To use a logic engine to do complex function dispatching based
    on more than just the type of parameters, such as

      ;; handle a generic 'push'
      (define-handler (push-action ?agent ?patient) 
       ... )

      ;; handle a 'push' of an npc
      (define-handler ((push-action ?agent ?patient) 
                      (isa ?patient npc-class)) 

      ;; handle a 'push' of a non-dwarf character by an angry dwarf
      (define-handler ((push-action ?agent ?patient) 
                       (and (isa ?agent dwarf-race)
                            (> (anger ?agent) 0.7))
                            (not (isa ?patient dwarf-race))) 



So I'm wondering - can any of this be precompiled, without having to
resort to run-time inference?

  1. World definition

    If the definitions are static, and the logic language is simpler
    than full-blown predicate logic, this may be possible to
    precompile. For example, a statement with unbound variables
    could be translated into an iteration over all possible
    elements, and an 'implies' could be translated into a
    conditional-set. Thus

      (implies (and (isa ?X bird) (not (isa ?X ostrich)))
               (canfly ?X))

    could get compiled into something akin to

      define function123 (X) 
        if check-relation (isa X bird) and 
           not check-relation (isa X ostrich)
        then set-attribute (X 'canfly)

      for-each X in set-of-all-objects
        function123 (X)

    If the definitions are only dynamic insofar that a human
    designer sometimes edits the file and tells the system to
    reload, that should be fine too.

    The problem would be if the definitions are dynamic, ie. if
    assertions on which those inferences are made could change at
    runtime. For example, if some object could at runtime 'cease' to
    be a bird, then the inference of its ability to fly would have
    to be invalidated. This brings us back to the problem from the
    last email, of maintaining consistent knowledge bases.

    But, as long as the inference isn't made based on any
    dynamically changing information, you might be able to compile a
    number of different kinds of inferences into imperative code.

  2. Function dispatching

    This is more tricky, as it involves querying the inference
    engine about the parameters at every function call. Now I see
    why inference caching would be *really* important. :)

    But if all the inferences are already precompiled, perhaps this
    would be as easy as just checking the objects for appropriate

    Then all three handlers could get clamped together using a
    common dispatch routine that checks for the conditions, such as:

      (define-handler ((push-action ?agent ?patient)) ... )

      (define-handler ((push-action ?agent ?patient) 
                       (isa ?patient npc-class)) ...)

      (define-handler ((push-action ?agent ?patient) 
                       (and (isa ?agent dwarf-race)
                            (> (anger ?agent) 0.7))
                            (not (isa ?patient dwarf-race))) 

    getting compiled into something like:

      define push-action-fn-001 (agent patient) 
        ...  // code for generic push

      define push-action-fn-002 (agent patient) 
        ...  // code for npc push

      define push-action-fn-003 (agent patient)
        ...  // code for angry dwarf push, etc.

      define push-action (agent patient)

        if (check-relation (isa agent dwarf-race) and
            get-attribute (anger agent) > 0.7 and
            not check-relation (isa patient dwarf-race))
          then push-action-fn-003 (agent patient)

        if (check-relation (isa patient npc-class))
          then push-action-fn-002 (agent patient)
        push-action-fn-001 (agent patient)

One would of course run into problems mentioned by Orleans in his
discussion of predicate dispatch, such as how to order the parameter
checking. But if one isn't worrying about full correctness, this
could be kluged by just checking and dispatching in the order in
which the functions were defined, or something like that...


Just some thoughts on compiling the inferences for a fairly static
mud system. The problem is that such a system would be quite
limited. It couldn't handle anything higher than first-order logic,
and even then the kinds of inferences it could do would probably be
limited to iterations over elements in the knowledge base and simple
operations on relations and attributes...

However: if all of the queries you're interested in involve checking
attributes or relations, or setting their value based on
combinations of other attributes or relations, then maybe this could
be precompiled and simply looked up at runtime? If all of the
queries only check for relations or attributes of particular
instances, maybe there's a way to make this really fast...


Robert Zubek
rob at cs.northwestern.edu 
MUD-Dev mailing list
MUD-Dev at kanga.nu

More information about the MUD-Dev mailing list