Fuzzy Prolog

Author(s): Claudio Vaucheret, Sergio Guadarrama, Francisco Bueno.

This package impements an extension of prolog to deal with uncertainty. We implement a fuzzy prolog that models interval-valued fuzzy logic. This approach is more general than other fuzzy prologs in two aspects:

  1. Truth values are sub-intervals on [0,1]. In fact, it could be a finite union of sub-intervals, as we will see below. Having a unique truth value is a particular case modeled with a unitary interval.
  2. Truth values are propagated through the rules by means of a set of aggregation operators. The definition of an aggregation operator is a generalization that subsumes conjunctive operators (triangular norms as min, prod, etc.), disjunctive operators (triangular co-norms as max, sum, etc.), average operators (averages as arithmetic average, cuasi-linear average, etc.) and hybrid operators (combinations of previous operators).

We add uncertainty using CLP(R) instead of implementing a new fuzzy resolution as other fuzzy prologs. In this way, we use the original inference mechanism of Prolog, and we use the constraints and its operations provided by CLP(R) to handle the concept of partial truth. We represent intervals as constrains over real numbers and aggregation operators as operations with constraints.

Each fuzzy predicate has an additional argument which represents its truth value. We use “:~” instead of “:-” to distinguish fuzzy clauses from prolog clauses. In fuzzy clauses, truth values are obtained via an aggregation operator. There is also some syntactic sugar for defining fuzzy predicates with certain membership functions, the fuzzy counterparts of crisp predicates, and the fuzzy negation of a fuzzy predicate.

Usage and interface

Documentation on new declarations

DECLARATION

(True) Usage::- aggr(Name).

Declares Name an aggregator. Its binary definition has to be provided. For example:

:- aggr myaggr.

myaggr(X,Y,Z):- Z .=. X*Y.
defines an aggregator identical to prod.

  • The following properties hold at call time:
    (basic_props:constant/1)Name is an atomic term (an atom or a number).

Documentation on exports

PREDICATE

(True) Usage::#(Name,Decl)

Defines fuzzy predicate Name from the declaration Decl.

  • The following properties hold upon exit:
    (basic_props:predname/1)Name is a Name/Arity structure denoting a predicate name:
    predname(P/A) :-
            atm(P),
            nnegint(A).
    

    (user(/home/clip/Systems/CiaoDE/trunk/ciao/library/fuzzy/fuzzy_doc):fuzzydecl/1)Decl is one of the following three:
    fuzzydecl(fuzzy_predicate(_1)).
    fuzzydecl(fuzzy(_1)).
    fuzzydecl(fnot(_1)).
    

PREDICATE

(True) Usage:fuzzy_predicate(Domain)

Defines a fuzzy predicate with piecewise linear continuous membership function. This is given by Domain, which is a list of pairs of domain-truth values, in increasing order and exhaustive. For example:

young :# fuzzy_predicate([(0,1),(35,1),(45,0),(120,0)]).
defines the predicate:
young(X,1):- X .>=. 0, X .<. 35.
young(X,M):- X .>=. 35, X .<. 45, 10*M .=. 45-X.
young(X,0):- X .>=. 45, X .=<. 120. 

  • The following properties should hold at call time:
    (basic_props:list/1)Domain is a list.

PREDICATE

(True) Usage:fuzzy(Name)

Defines a fuzzy predicate as the fuzzy counterpart of a crisp predicate Name. For example,

p_f :# fuzzy p/2
defines a new fuzzy predicate p_f/3 (the last argument is the truth value) with truth value equal to 0 if p/2 fails and 1 otherwise.

  • The following properties should hold at call time:
    (basic_props:predname/1)Name is a Name/Arity structure denoting a predicate name:
    predname(P/A) :-
            atm(P),
            nnegint(A).
    

PREDICATE

(True) Usage:fnot(Name)

Defines a fuzzy predicate as the fuzzy negation of another fuzzy predicate Name. For example,

notp_f :# fnot p_f/3
defines the predicate:
notp_f(X,Y,M) :-
        p_f(X,Y,Mp),
        M .=. 1 - Mp.

  • The following properties should hold at call time:
    (basic_props:predname/1)Name is a Name/Arity structure denoting a predicate name:
    predname(P/A) :-
            atm(P),
            nnegint(A).
    

PREDICATE

(True) Usage::~(Head,Body)

Defines a fuzzy clause for a fuzzy predicate. The clause contains calls to either fuzzy or crisp predicates. Calls to crisp predicates are automatically fuzzified. The last argument of Head is the truth value of the clause, which is obtained as the aggregation of the truth values of the body goals. An example:

:- module(young2,_,[fuzzy]).

young_couple(X,Y,Mu) :~ min
	age(X,X1),
	age(Y,Y1),
	young(X1,MuX),
	young(Y1,MuY).

age(john,37).
age(rose,39).

young :# fuzzy_predicate([(0,1),(35,1),(45,0),(120,0)]).

so that:
?- young_couple(john,rose,M).

M .=. 0.6 ? 

  • The following properties should hold at call time:
    (basic_props:callable/1)Head is a term which represents a goal, i.e., an atom or a structure.
    (user(/home/clip/Systems/CiaoDE/trunk/ciao/library/fuzzy/fuzzy_doc):fuzzybody/1)Body is a clause body plus an optional aggregation operator.

PROPERTY
A clause body, optionally prefixed by the name of an aggregation operator. The agregators currently provided are listed under faggregator/1. By default, the aggregator used is min.

(True) Usage:fuzzybody(B)

B is a clause body plus an optional aggregation operator.

    REGTYPE
    The first three are, respectively, the T-norms: minimum, product, and Lukasiewicz's. The last three are their corresponding T-conorms. Aggregators can be defined by the user, see aggr/1.
    faggregator(min).
    faggregator(prod).
    faggregator(luka).
    faggregator(max).
    faggregator(dprod).
    faggregator(dluka).
    

    Usage:faggregator(Aggr)

    Aggr is an aggregator which is cumulative, i.e., its application to several values by iterating pairwise the binary operation is safe.

      PREDICATE

      (True) Usage:=>(Aggr,A,B,Truth)

      The fuzzy implication A => B defined by aggregator Aggr, resulting in the truth value Truth.

      • The following properties should hold at call time:
        (user(/home/clip/Systems/CiaoDE/trunk/ciao/library/fuzzy/fuzzy_doc):faggregator/1)Aggr is an aggregator which is cumulative, i.e., its application to several values by iterating pairwise the binary operation is safe.
        (basic_props:callable/1)A is a term which represents a goal, i.e., an atom or a structure.
        (basic_props:callable/1)B is a term which represents a goal, i.e., an atom or a structure.
        (term_typing:var/1)Truth is a free variable.

      Other information

      An example program:
      :- module(dicesum5,_,[fuzzy]).
      
      % this example tries to measure which is the possibility
      % that a couple of values, obtained throwing two loaded dice, sum 5. Let
      % us suppose we only know that one die is loaded to obtain a small value
      % and the other is loaded to obtain a large value. 
      %
      % the query is  ? sum(5,M)
      %
      
      small :# fuzzy_predicate([(1,1),(2,1),(3,0.7),(4,0.3),(5,0),(6,0)]).
      large :# fuzzy_predicate([(1,0),(2,0),(3,0.3),(4,0.7),(5,1),(6,1)]).
      
      die1(X,M) :~
      	small(X,M).
      
      die2(X,M) :~
      	large(X,M).
      
      
      two_dice(X,Y,M):~ prod
      	die1(X,M1),
      	die2(Y,M2).
      
      sum(2,M) :~  
      	two_dice(1,1,M1).
      
      
      sum(5,M) :~ dprod
      	two_dice(4,1,M1),
      	two_dice(1,4,M2),
      	two_dice(3,2,M3),
      	two_dice(2,3,M4).
      
      
      There are more examples in the subdirectory fuzzy/examples of the distribution.

      Known bugs and planned improvements

      • General aggregations defined by users.
      • Inconsistent behaviour of meta-calls in fuzzy clauses.
      • Some meta-predicate constructions need be added, specially for 'disjunctive' fuzzy clauses, e.g., sum/2 in the dice example.