The BPL syntax is mainly the Prolog syntax but enriched with a built-in symbol “~” used for describing proximity relations (actually, fuzzy binary relations which are automatically converted into proximity or similarity relations) by means of what we call a proximity equation. Proximity equations are expressions of the form:

<symbol> ~ <symbol> = <proximity degree>

Although, a proximity equation represents an arbitrary fuzzy binary relation, its intuitive reading is that two constants, n-ary function symbols or n-ary predicate symbols are approximate or similar with a certain degree. That is, a proximity equation

a~b = α

can be understood in both directions: a is approximate/similar to b and b is approximate/similar to a with degree α. Therefore, a BPL program is a sequence of Prolog facts and rules followed by a sequence of proximity equations.

Example 1. Suppose a fragment of a database that stores a semantic network with information about people’s names and hair color, as well as the approximate relation between black, brown and blond hair.

% BPL directive % FACTS :- transitivity(no). is_a(john, person). is_a(peter, person). % SIMILARITY EQUATIONS is_a(mary, person). black~brown=0.6. hair_color(john,black). black~blond=0.3. hair_color(peter,brown). blond~brown=0.6. hair_color(mary,blond).

In a standard Prolog system, if we ask about whether peter’s hair is blond, “?- hair color(peter, blond)”, the system fails. However BPL allows us to obtain the answer “Yes with 0.6”.

To obtain this answer, the BPL system operates as follows: i) First it gen- erates the reflexive, symmetric closure of the fuzzy relation {R(black, brown) = 0.6, R(black,blond) = 0.3, R(blond,brown) = 0.6}, constructing a proxim- ity relation. ii) Then it tries to unify the goal hair color(peter, blond) and (eventually) the fact hair color(peter,brown). Because there exists the en- try R(brown, blond) = 0.6 in the constructed proximity relation (that is, brown is approximate to blond), the unification process succeeds with approximation degree 0.6.

The above example serves to illustrate both the syntax and the operational se- mantics of the language. Also, it is important to note that, in the last example, to inhibit the construction of the transitive closure (and therefore the construc- tion of a similarity relation) has been crucial to model the information properly and to obtain a convenient result. This effect is obtained by the BPL directive transitivity which disables or enables the construction of the transitive closure of a fuzzy relation during the compilation process. If a similarity relation would be generated, the system would constructed the entries R(brown, blond) = 0.3 and R(blond,brown) = 0.3, overlapping the initial approximation degree pro- vided by the user and leading to a wrong information modeling

**Unification and term comparison.**

BPL implements a weak unification operator, also denoted by ‘~’. It can be used, in the source language, to construct expressions like ‘Term1 ~ Term2 =:= Degree’ which is interpreted as follows: The expression is true if Term1 and Term2 are unifiable by proximity with approximation degree equal to Degree. In general, we can construct expressions ‘Term1 ~ Term2 <op> Degree’ where “<op>” is a comparison arithmetic operator or the symbol “=”. In the last case, the construction “Term1 ~ Term2 = Degree” success if Term1 and Term2 are weak unifiable with approximation degree Degree. Note that these are crisp expressions which are evaluated to the approximation degree 1.0.

Starting with BPL version 3.4, an explicit weak unification operator ‘~~’ was implemented, which is the fuzzy counterpart of the syntactical unification operator ‘=’ of standard Prolog. The expression ‘Term1 ~~ Term2’ success with degree D if Term1 and Term2 are unifiable by proximity with approximation degree D. Note that contrary to the last operator ‘~’, this is a fuzzy operator that returns approximation degrees between 0 and 1.0.

The expressions built with these operators may be introduced in a query as well as in the body of a clause.

**Fuzzy sets.**

BPL makes use of two directives to define and declare the structure of a linguistic variable: domain and fuzzy_set.

The domain directive allows to declare and define the universe of discourse or domain associated to a linguistic variable. The fuzzy_set directive allows to declare and define a list of fuzzy subsets (which are associated to the primary terms of a linguistic variable) on a predefined domain. At this time, it is possible to define two types of membership functions: either a trapezoidal function or a triangular function.

BPL provides modifiers that can be applied to fuzzy subsets. Additionally, a BPL program may include what we call “domain points” and “domain ranges”.

Example 2. BPL models the following fuzzy inference in a very natural way: “if $x$ is young then $x$ is fast” and “Robert is middle” then “Robert is somewhat fast”.

```
% DIRECTIVES
:-domain(age, 0, 100, years).
:-fuzzy_set(age,[young(0,0,30,50), middle(20,40,60,80),
old(50,80,100,100)]).
:-domain(speed, 0, 40, km/h).
:-fuzzy_set(speed,[slow(0,0,15,20), normal(15,20,25,40),
fast(25,30,40,40)]).
% FACTS AND RULES
speed(X, fast) :- age(X, young).
age(robert, middle).
```

Now, if we launch the goal: “?- speed(robert,somewhat#fast). The BPL system answers “Yes with 0.375”.

**Definite Clause Grammars.**

Version 3.6 has introduced the ability to work with Definite Clause Grammars (DCG) natively. DCGs were initially a notation for writing production rules for defining grammars, but now they can be used to parse, generate and check lists. In addition, they form a comfortable interface to difference lists.

**WordNet and BPL.**

In Bousi∼Prolog, the wn-connect subsystem must be made visible before using the built-ins (public predicates) defined in its modules. This can be done interactively, without the requirement of loading a BPL program first, by launching the following goal:

**BPL> ensure_loaded(wn(wn_connect)).**

** Yes**

** With approximation degree: 1 .**

or loading a program, with the directive ** :- wn connect.** in the first line of the program.

Remember that BPL directives must be used within a program. BPL directives to access the WordNet database and all the ancillary stuff for related predicates are the following:

**:- wn_connect.**

This directive performs the necessary actions to connect BPL to the WordNet resources. It must occur before any other access to WordNet, and it assumes that the environment variable **WNDB** has been set to the OS directory in which the WordNet database is stored.

There is an alternative to this directive if the environment variable cannot be set or the user simply does not want to:

**:- wn_connect(Directory).**

Where **Directory** is the directory where the WordNet database is located.

Next directives are responsible for generating proximity equations building an ontology:

**:- wn_gen_prox_equations(Msr, LL_of_Pats).**

Where **Msr** is the similarity measure which can have any of the following constant values: **path**, **wup** (Wu & Palmer, 1994), **lch** (Leacock & Chodorow, 1998), **res** (Resnik, 1995), **jcn** (Jiang & Conrath, 1997) and **lin** (Lin, 1998). The second argument **LL_of_Pats** is a list for which each element is another list containing the patterns that must be related by proximity equations.

The pattern can be either a word or the structure **Word:Type:Sense**, where **Word** is the word, **Type** is its type (either **n** for noun or **v** for verb) and **Sense** is the sense number in its synset.

If the pattern is simply a word, then a sense number of 1 is assumed, and its type is made to match to all other words in the same list.

**Filtering techniques.**

The BPL code can be optimized using filtering techniques. The idea is that the proximity equations in the program files and ontology can be filtered according to the lambda cut, so that the proximity equations that relate the terms with a degree lower than the lambda cut are discarded. Also, this technique prevents the generation of certain rules after the parsing phase, which greatly reduces non-determinism and, therefore, the search tree for a given goal.

Filtering can be activated or deactivated inside a BPL program, using a directive, or from the the BPL shell, using the command **fl**:

– Filtering directive: **:-filtering(+Boolean).** If the parameter Boolean is true, activates filtering, if it is false, disables filtering.

– Command fl: **fl +Boolean**. Same behaviour as the directive.

On the other hand, the lambda-cut can be modified using the BPL shell command **lc**.

**Tail recursion and Indexing.**

Bousi~Prolog implements WSLD-resolution by translating BPL code into Prolog code. The translation process is called BPL expansion and the translated code, TPL code. BPL expansion has two drawbacks: first, expanded rules breaks tail recursion and, second, it avoids the benefits of clause indexing techniques available in current implementations of Prolog.

**Tail recursion** is lost because when the rules of the BPL source program are expanded, partial degrees are composed by means of a last call to the internal predicate **degree_composition/2**. So, if a predicate in the source program is defined by tail recursion, when expanding the rule to obtain the TPL program, the last call is not anymore a call to the recursive predicate, and Prolog cannot perform last call optimization when the TPL program is consulted. This problem can be solved by computing the partial degrees first (by means of a call to the predicate **degree_composition/2**) and passing them, on the fly, through an accumulator parameter of each call in the body of a rule, keeping the last call as the recursive call.

A new directive **:-degree accumulator(+Boolean)** is provided for either enabling or disabling degree accumulator translation. Enabling this translation implies not breaking tail recursion optimization in BPL programs. By default, it is enabled (**Boolean=true**).

Problems with **indexing** arise because, for accomplishing a proximity based semantics with a crisp syntactic unification, it is necessary to flatten and linearise the rules of the BPL source program. In this way, two drawbacks occur: first, head unification is delayed up to the clause body, which avoids some Prolog compiler optimisations; and, second, the indexation on head arguments in the rules is lost. We have introduced some techniques to remedy some aspects of these indexing problems.

A new directive **:-indexing(+Boolean)** is at disposal of a BPL system user for either enabling or disabling indexing optimization. By default, it is enabled (**Boolean=true**).