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?
  1. 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))
    

  2. 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.

  3. 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.

  4. 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)), 
    

  5. 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))
    
  6. 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.

  7. 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
    
  8. There is better indexing support for #$Predicates, especially if the function version would not be reifiable.

Go to Top