Functions vs. Predicates
E-Mail Comments to: opencyc-doc@cyc.com
Last Update: 3/31/2002
Copyright© 1997-2002 Cycorp. All rights reserved.
Return to Table of Contents
This document should provide insight into the discussion of when to use functions and when to use predicates.
Given a real-world relationship between N items that is functional in
at least one of those items, should one create a #$Predicate or a
#$Function-Denotational to represent that relationship? If the
relationship is not at all functional, of course a Predicate must be
used. But if at least one of the "arguments" is functional, the
relationship could be represented with either a function or a
predicate. For example, one could represent the "successor"
relationship with either a #$BinaryPredicate,
(#$successor 1 2)
or with a #$UnaryFunction,
(#$SuccessorFn 1) which returns 2.
Which is better?
- There can be multiple, independent reasons to choose one or the
other. This means that sometimes, the best thing is to have BOTH a
predicate and the corresponding function.
Aside:
In the case where we do have equivalent functions and predicates, it
will be appropriate to write an axiom such as this in some appropriate mt:
(#$implies (#$termOfUnit ?X (#$GovernmentFn ?C)
(#$government ?C ?X))
- If you want to be able to add new terms to your language on the
fly, during inference, you must have the function version (else use a
SkolemFunction). For example, we know that practically every country
has a government. If all we had was #$government, we could use the
expression
(#$government ?C ?G)
to bind ?G to the government of ?C, but we would only find bindings in
cases where someone had bothered to introduce, by hand, a term
corresponding to the government of ?C.
Named functions are more desirable than Skolem functions, partly due to
clarity.
- If you want to be able to associate a piece of code to compute the
functional "argument", you should represent the relationship with an
EvaluatableFunction. What if we represented "plus" with a predicate?
(#$plus 2 2 ?X)
It is possible to make a predicate an instance of
#$EvaluatableRelationship, but the current system only supports an
#$evaluationDefn which expects all arguments to be fully-bound. So if
"plus" were an evaluatable predicate, we could answer the question
(#$plus 2 2 4)
as True, but we couldn't use the defn to find bindings for
?X as in the expression further above.
- In cases where you want to frequently assign a value to the
functional "argument", a predicate is most useful. For example, the
"height" relationship is functional -- for every PartiallyTangible,
there is some Distance that is the height of the object. We could use
a function --
(#$HeightFn #$Karen)
-- to generate that Distance. However, this would only be useful in
certain cases. If we want to declare that Karen has a particular
height, this is best accomplished with a Predicate:
(#$heightOfObject #$Karen (#$Foot-UnitOfMeasure 5.3)),
- In cases where you want to compare or constrain the value of a
functional arguement, a function version is useful:
(#$greaterThan (#$HeightFn #$Karen) (#$HeightFn #$Muffet))
- There are several reasoning modules with special support that can
be applied to Predicates: #$genlPreds, #$genlInverse, #$negationPreds,
#$negationInverse, etc. In order to use these, you have to have a
predicate.
- If the relationship is functional in more than one argument, you
can get by with a single Predicate but would require more than one
Function. For example, "atomic number" is a one-to-one relationship.
We can have a single predicate
(#$atomicNumber #$Helium 2)
which is functional in both of its arguments. Or, we could have
(#$AtomicNumberFn #$Helium) -> 2
(#$AtomicNumberOfFn 2) -> #$Helium
- There is better indexing support for #$Predicates, especially if the
function version would not be reifiable.
Go to Top